From 7cd1f277778ec881629b1e2e692216519dceffef Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Tue, 13 Dec 2022 09:22:00 +0200 Subject: [PATCH] initial commit --- .gitingnore | 2 + Dockerfile | 27 ++ LICENSE.txt | 21 + THIRD-PARTY-NOTICES.txt | 428 ++++++++++++++++++ pom.xml | 176 +++++++ settings.xml | 18 + .../zenodorepository/config/ConfigLoader.java | 8 + .../config/ConfigLoaderImpl.java | 60 +++ .../zenodorepository/config/DOIFunder.java | 27 ++ .../zenodorepository/config/ZenodoConfig.java | 140 ++++++ .../interfaces/ZenodoDeposit.java | 248 ++++++++++ .../mapper/DMPToZenodoMapper.java | 119 +++++ .../models/ZenodoAccessRight.java | 18 + .../models/ZenodoComunity.java | 19 + .../models/ZenodoContributor.java | 45 ++ .../models/ZenodoDeposit.java | 19 + .../models/ZenodoDepositMetadata.java | 158 +++++++ .../zenodorepository/models/ZenodoGrant.java | 18 + .../models/ZenodoRelator.java | 28 ++ src/main/resources/DOI_Funder.json | 70 +++ src/main/resources/application.properties | 3 + src/main/resources/zenodo.json | 12 + 22 files changed, 1664 insertions(+) create mode 100644 .gitingnore create mode 100644 Dockerfile create mode 100644 LICENSE.txt create mode 100644 THIRD-PARTY-NOTICES.txt create mode 100644 pom.xml create mode 100644 settings.xml create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/config/ZenodoConfig.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java create mode 100644 src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java create mode 100644 src/main/resources/DOI_Funder.json create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/zenodo.json diff --git a/.gitingnore b/.gitingnore new file mode 100644 index 0000000..e673575 --- /dev/null +++ b/.gitingnore @@ -0,0 +1,2 @@ +.idea/ +target/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..59eecd7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM maven:3.8.6-eclipse-temurin-17-focal + +RUN apt-get update +RUN apt-get install gpg -y + +ARG MAVEN_ACCOUNT_USR +ARG MAVEN_ACCOUNT_PSW +ARG REVISION +ARG MAVEN_GPG_PASSPHRASE +ARG MAVEN_GPG_KEYNAME +ARG PROFILE +ENV gpg_keyname=$MAVEN_GPG_KEYNAME +ENV gpg_passphrase=$MAVEN_GPG_PASSPHRASE +ENV server_username=$MAVEN_ACCOUNT_USR +ENV server_password=$MAVEN_ACCOUNT_PSW + +COPY settings.xml /root/.m2/settings.xml +COPY keypair.asc /tmp/keypair.asc +RUN if [ "$PROFILE" = "ossrh" ]; then \ + gpg --batch --import /tmp/keypair.asc; \ + fi + +WORKDIR /build/ + +COPY . . + +RUN mvn -Drevision=${REVISION} -P${PROFILE} clean deploy \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..47b2a43 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-2020 OpenAIRE AMKE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt new file mode 100644 index 0000000..4fdec79 --- /dev/null +++ b/THIRD-PARTY-NOTICES.txt @@ -0,0 +1,428 @@ +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +This component uses third party material from the projects listed below. +The original copyright notice and the license under which CITE +received such third party material are set forth below. CITE +reserves all other rights not expressly granted, whether by +implication, estoppel or otherwise. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: reception@cite.gr + +1. spring-boot-starter-parent +2. spring-boot-starter-web +3. json +4. repositorydepositbase + +spring-boot-starter-parent NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +========================================= +END OF spring-boot-starter-parent NOTICES, INFORMATION, AND LICENSE + +spring-boot-starter-web NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +========================================= +END OF spring-boot-starter-web NOTICES, INFORMATION, AND LICENSE \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..89fbe64 --- /dev/null +++ b/pom.xml @@ -0,0 +1,176 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.2 + + + + gr.cite.opendmp + repositorydepositzenodo + ${revision} + jar + + OpenDMP Repository Deposit Zenodo + OpenDMP Repository Deposit Zenodo + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo + + + MIT License + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo/src/branch/master/LICENSE.txt + repo + + + + + CITE S.A. + maven-central@cite.gr + CITE S.A. + https://www.cite.gr + + + + scm:git:git://code-repo.d4science.org + scm:git:ssh://code-repo.d4science.org + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo + + + + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + gr.cite.opendmp + repositorydepositbase + 1.0.0 + + + + org.json + json + 20160810 + + + + + + + maven-assembly-plugin + + + package + + single + + + + + + + eu.eudat.EuDatApplication + + + + jar-with-dependencies + + + + + + + + + ossrh + + + ossrh + https://s01.oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2 + + + + + + org.apache.maven.plugins + maven-install-plugin + 2.5.2 + + true + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + + + javadoc-generation + package + + jar + + + javadoc + + gr/** + + + README.txt + + + false + + + + + sources-generation + package + + jar + + + sources + + gr/** + + + README.txt + + + false + + + + + + + + + + + diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..e6874ab --- /dev/null +++ b/settings.xml @@ -0,0 +1,18 @@ + + + + ossrh + ${server_username} + ${server_password} + + + + + ossrh + + ${gpg_passphrase} + ${gpg_keyname} + + + + \ No newline at end of file diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java new file mode 100644 index 0000000..72873bf --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java @@ -0,0 +1,8 @@ +package eu.eudat.depositinterface.zenodorepository.config; + +import java.util.List; + +public interface ConfigLoader { + List getDOIFunders(); + ZenodoConfig getZenodoConfig(); +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java new file mode 100644 index 0000000..d43b9db --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java @@ -0,0 +1,60 @@ +package eu.eudat.depositinterface.zenodorepository.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service("zenodoConfigLoader") +public class ConfigLoaderImpl implements ConfigLoader{ + private static final Logger logger = LoggerFactory.getLogger(ConfigLoaderImpl.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + private List doiFunders = new ArrayList<>(); + private ZenodoConfig zenodoConfig; + + @Autowired + private Environment environment; + + @Override + public List getDOIFunders() { + if (doiFunders == null || doiFunders.isEmpty()) { + try { + List> tempdoiFunders = mapper.readValue(getStreamFromPath(environment.getProperty("configuration.doi_funder")), List.class); + doiFunders = tempdoiFunders.stream().map(map -> mapper.convertValue(map, DOIFunder.class) ).collect(Collectors.toList()); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + } + } + return doiFunders; + } + + @Override + public ZenodoConfig getZenodoConfig() { + if (zenodoConfig == null) { + try { + zenodoConfig = mapper.readValue(getStreamFromPath("zenodo.json"), ZenodoConfig.class); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + } + } + return zenodoConfig; + } + + private InputStream getStreamFromPath(String filePath) { + try { + return new FileInputStream(filePath); + } catch (FileNotFoundException e) { + logger.info("loading from classpath"); + return getClass().getClassLoader().getResourceAsStream(filePath); + } + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java new file mode 100644 index 0000000..88c7090 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java @@ -0,0 +1,27 @@ +package eu.eudat.depositinterface.zenodorepository.config; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DOIFunder { + + @JsonProperty("Funder") + private String funder; + @JsonProperty("DOI") + private String DOI; + + public String getFunder() { + return funder; + } + + public void setFunder(String funder) { + this.funder = funder; + } + + public String getDOI() { + return DOI; + } + + public void setDOI(String DOI) { + this.DOI = DOI; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ZenodoConfig.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ZenodoConfig.java new file mode 100644 index 0000000..763981e --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ZenodoConfig.java @@ -0,0 +1,140 @@ +package eu.eudat.depositinterface.zenodorepository.config; + +import com.fasterxml.jackson.annotation.JsonProperty; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; + +public class ZenodoConfig { + + private enum DepositType { + SystemDeposit(0), UserDeposit(1), BothWaysDeposit(2); + + private final int value; + + DepositType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static DepositType fromInteger(int value) { + switch (value) { + case 0: + return SystemDeposit; + case 1: + return UserDeposit; + case 2: + return BothWaysDeposit; + default: + throw new RuntimeException("Unsupported Deposit Type"); + } + } + } + + @JsonProperty("depositType") + private int depositType; + @JsonProperty("repositoryId") + private String repositoryId; + @JsonProperty("accessToken") + private String accessToken; + @JsonProperty("repositoryUrl") + private String repositoryUrl; + @JsonProperty("repositoryAuthorizationUrl") + private String repositoryAuthorizationUrl; + @JsonProperty("repositoryRecordUrl") + private String repositoryRecordUrl; + @JsonProperty("repositoryAccessTokenUrl") + private String repositoryAccessTokenUrl; + @JsonProperty("repositoryClientId") + private String repositoryClientId; + @JsonProperty("repositoryClientSecret") + private String repositoryClientSecret; + @JsonProperty("redirectUri") + private String redirectUri; + + public int getDepositType() { + return depositType; + } + public void setDepositType(int depositType) { + this.depositType = depositType; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getAccessToken() { + return accessToken; + } + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public String getRepositoryUrl() { + return repositoryUrl; + } + public void setRepositoryUrl(String repositoryUrl) { + this.repositoryUrl = repositoryUrl; + } + + public String getRepositoryAuthorizationUrl() { + return repositoryAuthorizationUrl; + } + public void setRepositoryAuthorizationUrl(String repositoryAuthorizationUrl) { + this.repositoryAuthorizationUrl = repositoryAuthorizationUrl; + } + + public String getRepositoryRecordUrl() { + return repositoryRecordUrl; + } + public void setRepositoryRecordUrl(String repositoryRecordUrl) { + this.repositoryRecordUrl = repositoryRecordUrl; + } + + public String getRepositoryAccessTokenUrl() { + return repositoryAccessTokenUrl; + } + public void setRepositoryAccessTokenUrl(String repositoryAccessTokenUrl) { + this.repositoryAccessTokenUrl = repositoryAccessTokenUrl; + } + + public String getRepositoryClientId() { + return repositoryClientId; + } + public void setRepositoryClientId(String repositoryClientId) { + this.repositoryClientId = repositoryClientId; + } + + public String getRepositoryClientSecret() { + return repositoryClientSecret; + } + public void setRepositoryClientSecret(String repositoryClientSecret) { + this.repositoryClientSecret = repositoryClientSecret; + } + + public String getRedirectUri() { + return redirectUri; + } + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public RepositoryDepositConfiguration toRepoConfig() { + RepositoryDepositConfiguration config = new RepositoryDepositConfiguration(); + config.setDepositType(this.depositType); + config.setRepositoryId(this.repositoryId); + config.setAccessToken(this.accessToken); + config.setRepositoryUrl(this.repositoryUrl); + config.setRepositoryAuthorizationUrl(this.repositoryAuthorizationUrl); + config.setRepositoryRecordUrl(this.repositoryRecordUrl); + config.setRepositoryAccessTokenUrl(this.repositoryAccessTokenUrl); + config.setRepositoryClientId(this.repositoryClientId); + config.setRepositoryClientSecret(this.repositoryClientSecret); + config.setRedirectUri(this.redirectUri); + return config; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java new file mode 100644 index 0000000..525cedb --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java @@ -0,0 +1,248 @@ +package eu.eudat.depositinterface.zenodorepository.interfaces; + +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import eu.eudat.depositinterface.zenodorepository.config.ConfigLoader; +import eu.eudat.depositinterface.zenodorepository.config.ZenodoConfig; +import eu.eudat.depositinterface.zenodorepository.mapper.DMPToZenodoMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.util.*; + +@Component +public class ZenodoDeposit implements RepositoryDeposit { + private static final Logger logger = LoggerFactory.getLogger(ZenodoDeposit.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private ConfigLoader configLoader; + private Environment environment; + + @Autowired + public ZenodoDeposit(ConfigLoader configLoader, Environment environment){ + this.configLoader = configLoader; + this.environment = environment; + } + + @Override + public String deposit(DMPDepositModel dmpDepositModel, String zenodoToken) throws Exception { + + RepositoryDepositConfiguration conf = this.getConfiguration(); + + if(zenodoToken == null){ + zenodoToken = conf.getAccessToken(); + } + + String zenodoUrl = conf.getRepositoryUrl(); + + // First step, post call to Zenodo, to create the entry. + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.APPLICATION_JSON); + eu.eudat.depositinterface.zenodorepository.models.ZenodoDeposit deposit = DMPToZenodoMapper.fromDMP(dmpDepositModel, "argos", "ARGOS", "https://argos.openaire.eu/", this.configLoader.getDOIFunders()); + + HttpEntity request = new HttpEntity<>(deposit, headers); + Map createResponse; + LinkedHashMap links; + String previousDOI = dmpDepositModel.getPreviousDOI(); + String unpublishedUrl = null; + String publishUrl; + String finalDoi; + try { + + if (previousDOI == null) { + String createUrl = zenodoUrl + "deposit/depositions" + "?access_token=" + zenodoToken; + createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody(); + links = (LinkedHashMap) createResponse.get("links"); + } + else { + unpublishedUrl = this.getUnpublishedDOI(zenodoUrl, previousDOI, zenodoToken, dmpDepositModel.getVersion()); + if (unpublishedUrl == null) { + //It requires more than one step to create a new version + //First, get the deposit related to the concept DOI + String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; + ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); + createResponse = listResponses.getBody()[0]; + links = (LinkedHashMap) createResponse.get("links"); + //Second, make the new version (not in the links?) + String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken; + createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class); + links = (LinkedHashMap) createResponse.get("links"); + //Third, get the new deposit + String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken; + createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); + links = (LinkedHashMap) createResponse.get("links"); + //At this point it might fail to perform the next requests so enclose them with try catch + try { + //Forth, update the new deposit's metadata + String updateUrl = links.get("self") + "?access_token=" + zenodoToken; + restTemplate.put(updateUrl, request); + //And finally remove pre-existing files from it + String fileListUrl = links.get("self") + "/files" + "?access_token=" + zenodoToken; + ResponseEntity fileListResponse = restTemplate.getForEntity(fileListUrl, Map[].class); + for (Map file : fileListResponse.getBody()) { + String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + zenodoToken; + restTemplate.delete(fileDeleteUrl); + } + } catch (Exception e) { + //In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed) + restTemplate.delete(latestDraftUrl); + throw e; + } + } + else { + String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; + ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); + createResponse = listResponses.getBody()[0]; + links = (LinkedHashMap) createResponse.get("links"); + } + } + + if (unpublishedUrl == null) { + // Second step, add the file to the entry. + File pdfFile = dmpDepositModel.getPdfFile(); + String fileName = dmpDepositModel.getPdfFileName(); + FileSystemResource fileSystemResource = new FileSystemResource(pdfFile); + HttpEntity addFileMapRequest = new HttpEntity<>(fileSystemResource, null); + + String addFileUrl = links.get("bucket") + "/" + fileName + "?access_token=" + zenodoToken; + restTemplate.put(addFileUrl, addFileMapRequest); + + ResponseEntity jsonFile = dmpDepositModel.getRdaJson(); + UUID jsonFileUUID = UUID.randomUUID(); + File tempJsonFile = new File(this.environment.getProperty("storage.temp") + jsonFileUUID + ".json"); + try (FileOutputStream jsonFos = new FileOutputStream(tempJsonFile)) { + jsonFos.write(jsonFile.getBody()); + jsonFos.flush(); + } + fileSystemResource = new FileSystemResource(tempJsonFile); + HttpHeaders jsonHeaders = new HttpHeaders(); + jsonHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE); + addFileMapRequest = new HttpEntity<>(fileSystemResource, jsonHeaders); + String jsonFileName = jsonFile.getHeaders().get("Content-Disposition").get(0).substring(jsonFile.getHeaders().get("Content-Disposition").get(0).lastIndexOf('=') + 1); + addFileUrl = links.get("bucket") + "/" + jsonFileName + "?access_token=" + zenodoToken; + restTemplate.put(addFileUrl, addFileMapRequest); + Files.deleteIfExists(tempJsonFile.toPath()); + + if(dmpDepositModel.getSupportingFilesZip() != null) { + File supportinFilesZip = dmpDepositModel.getSupportingFilesZip(); + String supportinFilesZipName = dmpDepositModel.getSupportingFilesZip().getName(); + fileSystemResource = new FileSystemResource(supportinFilesZip); + addFileMapRequest = new HttpEntity<>(fileSystemResource, null); + + addFileUrl = links.get("bucket") + "/" + supportinFilesZipName + "?access_token=" + zenodoToken; + restTemplate.put(addFileUrl, addFileMapRequest); + } + + // Third post call to Zenodo to publish the entry and return the DOI. + publishUrl = links.get("publish") + "?access_token=" + zenodoToken; + } + else { + publishUrl = unpublishedUrl + "?access_token=" + zenodoToken; + } + + return this.publish(publishUrl); + + } catch (HttpClientErrorException | HttpServerErrorException ex) { + Map parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), HashMap.class); + throw new IOException(parsedException.get("message"), ex); + } + + } + + private String publish(String publishUrl){ + RestTemplate restTemplate = new RestTemplate(); + Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); + return (String) publishResponce.get("conceptdoi"); + } + + + @Override + public RepositoryDepositConfiguration getConfiguration() { + ZenodoConfig zenodoConfig = this.configLoader.getZenodoConfig(); + return zenodoConfig.toRepoConfig(); + } + + @Override + public String authenticate(String code){ + + RepositoryDepositConfiguration conf = this.getConfiguration(); + + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("client_id", conf.getRepositoryClientId()); + map.add("client_secret", conf.getRepositoryClientSecret()); + map.add("grant_type", "authorization_code"); + map.add("code", code); + map.add("redirect_uri", conf.getRedirectUri()); + HttpEntity> request = new HttpEntity<>(map, headers); + + try { + Map values = restTemplate.postForObject(conf.getRepositoryAccessTokenUrl(), request, Map.class); + //ZenodoResponseToken zenodoResponseToken = new ZenodoResponseToken(); + Map user = (Map) values.get("user"); +// zenodoResponseToken.setUserId((String) user.get("id")); +// zenodoResponseToken.setEmail((String) user.get("email")); +// zenodoResponseToken.setExpiresIn((Integer) values.get("expires_in")); +// zenodoResponseToken.setAccessToken((String) values.get("access_token")); +// zenodoResponseToken.setRefreshToken((String) values.get("refresh_token")); + + //return zenodoResponseToken; + return (String) values.get("access_token"); + } catch (HttpClientErrorException ex) { + logger.error(ex.getResponseBodyAsString(), ex); + } + + return null; + } + + private String getUnpublishedDOI(String zenodoUrl, String DOI, String token, Integer version) { + try { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.APPLICATION_JSON); + Map createResponse = null; + LinkedHashMap links = null; + LinkedHashMap metadata = null; + String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + DOI + "\"&access_token=" + token; + ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); + createResponse = listResponses.getBody()[0]; + metadata = (LinkedHashMap) createResponse.get("metadata"); + links = (LinkedHashMap) createResponse.get("links"); + + if (metadata.get("version").equals(version.toString())) { + return links.get("publish"); + } else { + return null; + } + }catch (Exception e) { + logger.warn(e.getMessage(), e); + return null; + } + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java new file mode 100644 index 0000000..efc0375 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java @@ -0,0 +1,119 @@ +package eu.eudat.depositinterface.zenodorepository.mapper; + +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.models.OrganisationDepositModel; +import eu.eudat.depositinterface.models.UserDMPDepositModel; +import eu.eudat.depositinterface.zenodorepository.config.DOIFunder; +import eu.eudat.depositinterface.zenodorepository.models.*; + +import java.time.Instant; +import java.util.*; +import java.util.stream.Collectors; + +public class DMPToZenodoMapper { + + public static ZenodoDeposit fromDMP(DMPDepositModel dmp, String zenodoCommunity, String zenodoAffiliation, String domain, List doiFunders) { + Map extraProperties = dmp.getExtraProperties() != null ? new org.json.JSONObject(dmp.getExtraProperties()).toMap() : new HashMap<>(); + ZenodoDeposit deposit = new ZenodoDeposit(); + deposit.setMetadata(new ZenodoDepositMetadata()); + deposit.getMetadata().setTitle(dmp.getLabel()); + deposit.getMetadata().setUploadType("publication"); + deposit.getMetadata().setPublicationType("datamanagementplan"); + deposit.getMetadata().setDescription((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

")); + deposit.getMetadata().setVersion(String.valueOf(dmp.getVersion())); + if(zenodoCommunity != null && !zenodoAffiliation.isEmpty()) { + ZenodoComunity community = new ZenodoComunity(); + community.setIdentifier(zenodoCommunity); + deposit.getMetadata().setCommunities(Collections.singletonList(community)); + } + if (extraProperties.get("visible") == null) { + deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED); + deposit.getMetadata().setAccessConditions(""); + } else { + if (((Boolean) extraProperties.get("visible"))) { + Instant publicationDate = Instant.parse(extraProperties.get("publicDate").toString()); + if (publicationDate.isBefore(Instant.now())) { + deposit.getMetadata().setAccessRight(ZenodoAccessRight.OPEN); + } else { + deposit.getMetadata().setAccessRight(ZenodoAccessRight.EMBARGOED); + deposit.getMetadata().setEmbargoDate(publicationDate.toString()); + } + + if (extraProperties.get("license") != null) { + deposit.getMetadata().setLicense(((Map) extraProperties.get("license")).get("pid").toString()); + } + } else { + deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED); + deposit.getMetadata().setAccessConditions(""); + } + } + if (dmp.isPublic()) { + ZenodoRelator relator = new ZenodoRelator(); + relator.setIdentifier(domain + "/external/zenodo/" + dmp.getId().toString()); + relator.setRelation("isIdenticalTo"); + deposit.getMetadata().setRelatedIdentifiers(Collections.singletonList(relator)); + } + deposit.getMetadata().setContributors(new LinkedList<>()); + List contributors = dmp.getUsers().stream().map(userDMP -> { + ZenodoContributor contributor = new ZenodoContributor(); + contributor.setName(userDMP.getUser().getName()); + contributor.setType("ProjectMember"); + if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) { + contributor.setAffiliation(dmp.getOrganisations() + .stream().map(OrganisationDepositModel::getLabel).collect(Collectors.joining(", "))); + } else { + if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) { + contributor.setAffiliation(zenodoAffiliation); + } + } + return contributor; + }).collect(Collectors.toList()); + + List researchers = dmp.getResearchers().stream().map(researcher -> { + ZenodoContributor contributor = new ZenodoContributor(); + contributor.setName(researcher.getLabel()); + contributor.setType("Researcher"); + String referenceHead = researcher.getReference().split(":")[0]; + String referenceTail = researcher.getReference().replace(referenceHead + ":", ""); + contributor.setAffiliation(referenceHead); + if (referenceHead.equalsIgnoreCase("ORCID")) { + contributor.setOrcid(referenceTail); + } + return contributor; + }).collect(Collectors.toList()); + + deposit.getMetadata().getContributors().addAll(contributors); + deposit.getMetadata().getContributors().addAll(researchers); + + if (dmp.getGrant().getReference() == null) { + dmp.getGrant().setReference("dmp:" + dmp.getGrant().getId()); + } + String grantReferenceHead = dmp.getGrant().getReference().split(":")[0]; + if (grantReferenceHead.equals("openaire")) { + String grantReferenceTail = dmp.getGrant().getReference().split(":")[3]; + DOIFunder doiFunder = doiFunders.stream() + .filter(doiFunder1 -> dmp.getGrant().getFunder().getLabel().contains(doiFunder1.getFunder()) || doiFunder1.getFunder().contains(dmp.getGrant().getFunder().getLabel())) + .findFirst().orElse(null); + if (doiFunder != null) { + String finalId = doiFunder.getDOI() + "::" + grantReferenceTail; + ZenodoGrant grant = new ZenodoGrant(); + grant.setId(finalId); + deposit.getMetadata().setGrants(Collections.singletonList(grant)); + } + } + ZenodoContributor creator = new ZenodoContributor(); + creator.setName(dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMPDepositModel.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName()); + if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) { + creator.setAffiliation(dmp.getOrganisations() + .stream().map(OrganisationDepositModel::getLabel).collect(Collectors.joining(", "))); + } else { + if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) { + creator.setAffiliation(zenodoAffiliation); + } + } + deposit.getMetadata().setCreators(Collections.singletonList(creator)); + + return deposit; + } +} + diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java new file mode 100644 index 0000000..0cf6cd4 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java @@ -0,0 +1,18 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ZenodoAccessRight { + RESTRICTED("restricted"), EMBARGOED("embargoed"), OPEN("open"); + + private final String value; + + ZenodoAccessRight(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java new file mode 100644 index 0000000..a04a19c --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java @@ -0,0 +1,19 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoComunity { + + private String identifier; + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java new file mode 100644 index 0000000..c172d52 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java @@ -0,0 +1,45 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoContributor { + private String name; + private String type; + private String affiliation; + private String orcid; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getAffiliation() { + return affiliation; + } + + public void setAffiliation(String affiliation) { + this.affiliation = affiliation; + } + + public String getOrcid() { + return orcid; + } + + public void setOrcid(String orcid) { + this.orcid = orcid; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java new file mode 100644 index 0000000..c27c253 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java @@ -0,0 +1,19 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoDeposit { + + private ZenodoDepositMetadata metadata; + + public ZenodoDepositMetadata getMetadata() { + return metadata; + } + + public void setMetadata(ZenodoDepositMetadata metadata) { + this.metadata = metadata; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java new file mode 100644 index 0000000..041f962 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java @@ -0,0 +1,158 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoDepositMetadata { + + private String title; + + @JsonProperty("upload_type") + private String uploadType; + + @JsonProperty("publication_type") + private String publicationType; + + private String description; + + private String version; + + private List communities; + + @JsonProperty("access_right") + private ZenodoAccessRight accessRight; + + @JsonProperty("access_conditions") + private String accessConditions; + + @JsonProperty("embargo_date") + private String embargoDate; + + private String license; + + @JsonProperty("related_identifiers") + private List relatedIdentifiers; + + private List contributors; + + private List grants; + + private List creators; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getUploadType() { + return uploadType; + } + + public void setUploadType(String uploadType) { + this.uploadType = uploadType; + } + + public String getPublicationType() { + return publicationType; + } + + public void setPublicationType(String publicationType) { + this.publicationType = publicationType; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getCommunities() { + return communities; + } + + public void setCommunities(List communities) { + this.communities = communities; + } + + public ZenodoAccessRight getAccessRight() { + return accessRight; + } + + public void setAccessRight(ZenodoAccessRight accessRight) { + this.accessRight = accessRight; + } + + public String getAccessConditions() { + return accessConditions; + } + + public void setAccessConditions(String accessConditions) { + this.accessConditions = accessConditions; + } + + public String getEmbargoDate() { + return embargoDate; + } + + public void setEmbargoDate(String embargoDate) { + this.embargoDate = embargoDate; + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public List getRelatedIdentifiers() { + return relatedIdentifiers; + } + + public void setRelatedIdentifiers(List relatedIdentifiers) { + this.relatedIdentifiers = relatedIdentifiers; + } + + public List getContributors() { + return contributors; + } + + public void setContributors(List contributors) { + this.contributors = contributors; + } + + public List getGrants() { + return grants; + } + + public void setGrants(List grants) { + this.grants = grants; + } + + public List getCreators() { + return creators; + } + + public void setCreators(List creators) { + this.creators = creators; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java new file mode 100644 index 0000000..d37c657 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java @@ -0,0 +1,18 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoGrant { + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java new file mode 100644 index 0000000..8196f63 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java @@ -0,0 +1,28 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoRelator { + + private String identifier; + private String relation; + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public String getRelation() { + return relation; + } + + public void setRelation(String relation) { + this.relation = relation; + } +} diff --git a/src/main/resources/DOI_Funder.json b/src/main/resources/DOI_Funder.json new file mode 100644 index 0000000..9f1c485 --- /dev/null +++ b/src/main/resources/DOI_Funder.json @@ -0,0 +1,70 @@ +[ + { + "Funder": "Australian Research Council", + "DOI": "10.13039/501100000923" + }, + { + "Funder": "Austrian Science Fund", + "DOI": "10.13039/501100002428" + }, + { + "Funder": "European Commission", + "DOI": "10.13039/501100000780" + }, + { + "Funder": "European Environment Agency", + "DOI": "10.13039/501100000806" + }, + { + "Funder": "Academy of Finland", + "DOI": "10.13039/501100002341" + }, + { + "Funder": "Hrvatska Zaklada za Znanost", + "DOI": "10.13039/501100004488" + }, + { + "Funder": "Fundação para a Ciência e a Tecnologia", + "DOI": "10.13039/501100001871" + }, + { + "Funder": "Ministarstvo Prosvete, Nauke i Tehnološkog Razvoja", + "DOI": "10.13039/501100004564" + }, + { + "Funder": "Ministarstvo Znanosti, Obrazovanja i Sporta", + "DOI": "10.13039/501100006588" + }, + { + "Funder": "National Health and Medical Research Council", + "DOI": "10.13039/501100000925" + }, + { + "Funder": "National Institutes of Health", + "DOI": "10.13039/100000002" + }, + { + "Funder": "National Science Foundation", + "DOI": "10.13039/100000001" + }, + { + "Funder": "Nederlandse Organisatie voor Wetenschappelijk Onderzoek", + "DOI": "10.13039/501100003246" + }, + { + "Funder": "Research Councils", + "DOI": "10.13039/501100000690" + }, + { + "Funder": "Schweizerischer Nationalfonds zur Förderung der wissenschaftlichen Forschung", + "DOI": "10.13039/501100001711" + }, + { + "Funder": "Science Foundation Ireland", + "DOI": "10.13039/501100001602" + }, + { + "Funder": "Wellcome Trust", + "DOI": "10.13039/100004440" + } +] \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..10cc38d --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,3 @@ +configuration.doi_funder=DOI_Funder.json +storage.temp=${ZENODO_TMP} +configuration.zenodo=${ZENODO_CONF} diff --git a/src/main/resources/zenodo.json b/src/main/resources/zenodo.json new file mode 100644 index 0000000..7d7d81e --- /dev/null +++ b/src/main/resources/zenodo.json @@ -0,0 +1,12 @@ +{ + "depositType": 2, + "repositoryId": "Zenodo", + "accessToken": "pcqw4LGLrhp17FF5GoXNCXakkEi82ThchZw7Tk4qh74VrDE3EmliG3UlhYtd", + "repositoryUrl": "https://sandbox.zenodo.org/api/", + "repositoryAuthorizationUrl": "https://sandbox.zenodo.org/oauth/authorize", + "repositoryRecordUrl": "https://sandbox.zenodo.org/record/", + "repositoryAccessTokenUrl": "https://sandbox.zenodo.org/oauth/token", + "repositoryClientId": "hEmVRNc1OzRmWyi2GDR3XVKbhG3OtfJXLXkkOGXx", + "repositoryClientSecret": "7VSU0NjiAg0P3mv14wemMYy2XhvlmV6F7xoszxPH4ZDx98v8FdMpBbxlncqr", + "redirectUri": "http://localhost:4200/login/external/zenodo" +} \ No newline at end of file