From b6af310532d20489ae1b1cb7d39af04c16716c08 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Fri, 26 Jan 2024 11:07:11 +0200 Subject: [PATCH] Initial Commit --- .gitignore | 2 + Dockerfile | 36 + LICENSE.txt | 21 + README.md | 9 + THIRD-PARTY-NOTICES.txt | 428 ++++ core/pom.xml | 36 + .../FileStorageConfiguration.java | 9 + .../configuration/FileStorageProperties.java | 24 + .../executor/RdaFileTransformer.java | 93 + .../eudat/file/transformer/rda/Contact.java | 144 ++ .../eudat/file/transformer/rda/ContactId.java | 150 ++ .../file/transformer/rda/Contributor.java | 180 ++ .../file/transformer/rda/ContributorId.java | 151 ++ .../eu/eudat/file/transformer/rda/Cost.java | 370 ++++ .../eudat/file/transformer/rda/Dataset.java | 619 ++++++ .../eudat/file/transformer/rda/DatasetId.java | 160 ++ .../file/transformer/rda/Distribution.java | 410 ++++ .../eu/eudat/file/transformer/rda/Dmp.java | 551 +++++ .../eu/eudat/file/transformer/rda/DmpId.java | 152 ++ .../eudat/file/transformer/rda/FunderId.java | 150 ++ .../eudat/file/transformer/rda/Funding.java | 183 ++ .../eudat/file/transformer/rda/GrantId.java | 149 ++ .../eu/eudat/file/transformer/rda/Host.java | 772 +++++++ .../eudat/file/transformer/rda/Language.java | 229 ++ .../eudat/file/transformer/rda/License.java | 111 + .../transformer/rda/MetadataStandardId.java | 149 ++ .../eudat/file/transformer/rda/Metadatum.java | 364 +++ .../eudat/file/transformer/rda/PidSystem.java | 64 + .../eudat/file/transformer/rda/Project.java | 211 ++ .../eudat/file/transformer/rda/RDAModel.java | 58 + .../transformer/rda/SecurityAndPrivacy.java | 107 + .../transformer/rda/TechnicalResource.java | 107 + .../rda/mapper/ContactIdRDAMapper.java | 20 + .../rda/mapper/ContactRDAMapper.java | 39 + .../rda/mapper/ContributorIdRDAMapper.java | 22 + .../rda/mapper/ContributorRDAMapper.java | 90 + .../transformer/rda/mapper/CostRDAMapper.java | 114 + .../rda/mapper/DatasetIdRDAMapper.java | 139 ++ .../rda/mapper/DatasetRDAMapper.java | 436 ++++ .../rda/mapper/DistributionRDAMapper.java | 439 ++++ .../rda/mapper/DmpIdRDAMapper.java | 19 + .../transformer/rda/mapper/DmpRDAMapper.java | 209 ++ .../rda/mapper/FunderIdRDAMapper.java | 19 + .../rda/mapper/FundingRDAMapper.java | 48 + .../rda/mapper/GrantIdRDAMapper.java | 13 + .../transformer/rda/mapper/HostRDAMapper.java | 262 +++ .../rda/mapper/KeywordRDAMapper.java | 30 + .../rda/mapper/LanguageRDAMapper.java | 45 + .../rda/mapper/LicenseRDAMapper.java | 135 ++ .../rda/mapper/MetadataRDAMapper.java | 230 ++ .../mapper/MetadataStandardIdRDAMapper.java | 13 + .../rda/mapper/ProjectRDAMapper.java | 69 + .../mapper/SecurityAndPrivacyRDAMapper.java | 152 ++ .../mapper/TechnicalResourceRDAMapper.java | 153 ++ .../TemplateFieldSearcher.java | 63 + .../transformer/utils/json/JsonSearcher.java | 81 + .../service/storage/FileStorageService.java | 44 + .../utils/string/MyStringUtils.java | 21 + pom.xml | 37 + settings.xml | 29 + web/pom.xml | 59 + .../FileTransformerApplication.java | 16 + .../config/SecurityConfiguration.java | 76 + .../controller/FileTransformerController.java | 48 + web/src/main/resources/config/application.yml | 11 + web/src/main/resources/config/cache.yml | 16 + web/src/main/resources/config/pdf.yml | 3 + web/src/main/resources/config/security.yml | 20 + web/src/main/resources/config/server.yml | 12 + web/src/main/resources/config/storage.yml | 4 + web/src/main/resources/documents/h2020.docx | Bin 0 -> 30266 bytes .../resources/documents/h2020_dataset.docx | Bin 0 -> 20315 bytes web/src/main/resources/documents/styles.xml | 2 + .../resources/documents/~$020_dataset.docx | Bin 0 -> 162 bytes .../main/resources/internal/fetchConfig.xml | 13 + web/src/main/resources/internal/iso-4217.xml | 1949 +++++++++++++++++ .../main/resources/internal/rda-lang-map.json | 186 ++ web/src/main/resources/pidLinks.json | 100 + 78 files changed, 11685 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 THIRD-PARTY-NOTICES.txt create mode 100644 core/pom.xml create mode 100644 core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageConfiguration.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageProperties.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/executor/RdaFileTransformer.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Contact.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/ContactId.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Contributor.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/ContributorId.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Cost.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Dataset.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/DatasetId.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Distribution.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Dmp.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/DmpId.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/FunderId.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Funding.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/GrantId.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Host.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Language.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/License.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/MetadataStandardId.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Metadatum.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/PidSystem.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/Project.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/RDAModel.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/SecurityAndPrivacy.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/TechnicalResource.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactIdRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorIdRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/CostRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetIdRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/DistributionRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpIdRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/FunderIdRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/FundingRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/GrantIdRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/HostRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/KeywordRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/LanguageRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/LicenseRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataStandardIdRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/ProjectRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/SecurityAndPrivacyRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/rda/mapper/TechnicalResourceRDAMapper.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/utils/descriptionTemplate/TemplateFieldSearcher.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/utils/json/JsonSearcher.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/utils/service/storage/FileStorageService.java create mode 100644 core/src/main/java/eu/eudat/file/transformer/utils/string/MyStringUtils.java create mode 100644 pom.xml create mode 100644 settings.xml create mode 100644 web/pom.xml create mode 100644 web/src/main/java/eu/eudat/file/transformer/FileTransformerApplication.java create mode 100644 web/src/main/java/eu/eudat/file/transformer/config/SecurityConfiguration.java create mode 100644 web/src/main/java/eu/eudat/file/transformer/controller/FileTransformerController.java create mode 100644 web/src/main/resources/config/application.yml create mode 100644 web/src/main/resources/config/cache.yml create mode 100644 web/src/main/resources/config/pdf.yml create mode 100644 web/src/main/resources/config/security.yml create mode 100644 web/src/main/resources/config/server.yml create mode 100644 web/src/main/resources/config/storage.yml create mode 100644 web/src/main/resources/documents/h2020.docx create mode 100644 web/src/main/resources/documents/h2020_dataset.docx create mode 100644 web/src/main/resources/documents/styles.xml create mode 100644 web/src/main/resources/documents/~$020_dataset.docx create mode 100644 web/src/main/resources/internal/fetchConfig.xml create mode 100644 web/src/main/resources/internal/iso-4217.xml create mode 100644 web/src/main/resources/internal/rda-lang-map.json create mode 100644 web/src/main/resources/pidLinks.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92322c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +target/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f3ee643 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +####################################### Build stage ####################################### +FROM maven:3.9-eclipse-temurin-21-alpine AS build-stage + +ARG MAVEN_ACCOUNT_USR +ARG MAVEN_ACCOUNT_PSW +ARG REVISION +ARG PROFILE +ARG DEV_PROFILE_URL +ENV server_username=$MAVEN_ACCOUNT_USR +ENV server_password=$MAVEN_ACCOUNT_PSW + +COPY pom.xml /build/ +COPY core /build/core/ +COPY web /build/web/ +COPY settings.xml /root/.m2/settings.xml +RUN rm -f /build/web/src/main/resources/config/app.env +RUN rm -f /build/web/src/main/resources/config/*-dev.yml +# RUN rm -f /build/web/src/main/resources/logging/*.xml + +WORKDIR /build/ + +RUN mvn -Drevision=${REVISION} -DdevProfileUrl=${DEV_PROFILE_URL} -P${PROFILE} dependency:go-offline +# Build project +RUN mvn -Drevision=${REVISION} -DdevProfileUrl=${DEV_PROFILE_URL} -P${PROFILE} clean package + +######################################## Run Stage ######################################## +FROM eclipse-temurin:21-jre-alpine + +ARG PROFILE +ARG REVISION +ENV SERVER_PORT=8080 +EXPOSE ${SERVER_PORT} + +COPY --from=build-stage /build/web/target/file-transformer-rda-web-${REVISION}.jar /app/file-transformer-rda-web-web.jar + +ENTRYPOINT ["java","-Dspring.config.additional-location=file:/config/","-Dspring.profiles.active=${PROFILE}","-Djava.security.egd=file:/dev/./urandom","-jar","/app/file-transformer-rda-web.jar"] \ 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/README.md b/README.md new file mode 100644 index 0000000..a134918 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Using RDA File Transformer with Argos + +The repository-file-transformer-rda module implements the [https://code-repo.d4science.org/MaDgiK-CITE/file-transformer-base](https://) interface for the RDA Json file format. + +## Setup + +After creating the jar from the project, environment variables should be set since they are used in the application.properties +1) STORAGE_TMP_ZENODO - a temporary storage needed +2) CONFIGURATION_ZENODO - path to json file which includes the configuration for the repository \ No newline at end of file diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt new file mode 100644 index 0000000..cd902f1 --- /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. file-transformer-base + +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/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000..6fe6d4e --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + gr.cite.opendmp + file-transformer-rda-parent + ${revision} + ../pom.xml + + + file-transformer-rda + ${revision} + jar + + + 21 + 21 + 21 + 1.0.0-SNAPSHOT + 0.0.3 + + + + + gr.cite.opendmp + file-transformer-base + ${transformer-base.version} + + + + org.springframework.boot + spring-boot-starter-webflux + + + diff --git a/core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageConfiguration.java b/core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageConfiguration.java new file mode 100644 index 0000000..85cdbaf --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageConfiguration.java @@ -0,0 +1,9 @@ +package eu.eudat.file.transformer.configuration; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(FileStorageProperties.class) +public class FileStorageConfiguration { +} diff --git a/core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageProperties.java b/core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageProperties.java new file mode 100644 index 0000000..5ba191d --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/configuration/FileStorageProperties.java @@ -0,0 +1,24 @@ +package eu.eudat.file.transformer.configuration; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.bind.ConstructorBinding; + +@ConfigurationProperties(prefix = "file.storage") +public class FileStorageProperties { + private final String temp; + private final String transientPath; + + @ConstructorBinding + public FileStorageProperties(String temp, String transientPath) { + this.temp = temp; + this.transientPath = transientPath; + } + + public String getTemp() { + return temp; + } + + public String getTransientPath() { + return transientPath; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/executor/RdaFileTransformer.java b/core/src/main/java/eu/eudat/file/transformer/executor/RdaFileTransformer.java new file mode 100644 index 0000000..aa664bd --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/executor/RdaFileTransformer.java @@ -0,0 +1,93 @@ +package eu.eudat.file.transformer.executor; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import eu.eudat.file.transformer.interfaces.FileTransformerClient; +import eu.eudat.file.transformer.interfaces.FileTransformerConfiguration; +import eu.eudat.file.transformer.models.description.DescriptionFileTransformerModel; +import eu.eudat.file.transformer.models.dmp.DmpFileTransformerModel; +import eu.eudat.file.transformer.models.misc.FileEnvelope; +import eu.eudat.file.transformer.models.misc.FileFormat; +import eu.eudat.file.transformer.rda.Dataset; +import eu.eudat.file.transformer.rda.Dmp; +import eu.eudat.file.transformer.rda.RDAModel; +import eu.eudat.file.transformer.rda.mapper.DatasetRDAMapper; +import eu.eudat.file.transformer.rda.mapper.DmpRDAMapper; +import eu.eudat.file.transformer.utils.service.storage.FileStorageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.management.InvalidApplicationException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.List; + +@Service +public class RdaFileTransformer implements FileTransformerClient { + + private final DmpRDAMapper dmpRDAMapper; + private final DatasetRDAMapper descriptionRDAMapper; + private final ObjectMapper mapper; + private final FileStorageService fileStorageService; + + @Autowired + public RdaFileTransformer(DmpRDAMapper dmpRDAMapper, DatasetRDAMapper descriptionRDAMapper, FileStorageService fileStorageService) { + this.dmpRDAMapper = dmpRDAMapper; + this.descriptionRDAMapper = descriptionRDAMapper; + this.fileStorageService = fileStorageService; + mapper = new ObjectMapper(); + mapper.registerModule(new JavaTimeModule()); + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + } + @Override + public FileEnvelope exportDmp(DmpFileTransformerModel dmpFileTransformerModel) throws InvalidApplicationException, IOException { + Dmp dmp = this.dmpRDAMapper.toRDA(dmpFileTransformerModel); + RDAModel rdaModel = new RDAModel(); + rdaModel.setDmp(dmp); + String dmpJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rdaModel); + FileEnvelope result = new FileEnvelope(); + result.setFilename(dmpFileTransformerModel.getLabel() + ".json"); + result.setFile(this.fileStorageService.storeFile(dmpJson.getBytes(StandardCharsets.UTF_8))); + return result; + } + + @Override + public FileEnvelope exportDescription(DescriptionFileTransformerModel descriptionFileTransformerModel, String format) throws InvalidApplicationException, IOException { + Dataset dataset = this.descriptionRDAMapper.toRDA(descriptionFileTransformerModel, this.dmpRDAMapper.toRDA(descriptionFileTransformerModel.getDmp())); + String dmpJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(dataset); + FileEnvelope result = new FileEnvelope(); + result.setFilename(descriptionFileTransformerModel.getLabel() + ".json"); + result.setFile(this.fileStorageService.storeFile(dmpJson.getBytes(StandardCharsets.UTF_8))); + return result; + } + + @Override + public DmpFileTransformerModel importDmp(FileEnvelope fileEnvelope) { + /*try { //TODO + String jsonString = String.valueOf(this.fileStorageService.readFile(fileEnvelope.getFile())); + RDAModel rda = mapper.readValue(jsonString, RDAModel.class); + DmpFileTransformerModel model = this.dmpRDAMapper.toEntity(rda.getDmp(), ) + } catch (JsonProcessingException e) { + + }*/ + return null; + } + + @Override + public DescriptionFileTransformerModel importDescription(FileEnvelope fileEnvelope) { + return null; + } + + @Override + public FileTransformerConfiguration getConfiguration() { + List supportedFormats = List.of(new FileFormat("json", false, null)); + FileTransformerConfiguration configuration = new FileTransformerConfiguration(); + configuration.setFileTransformerId("json"); + configuration.setExportVariants(supportedFormats); + configuration.setImportVariants(supportedFormats); + return configuration; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Contact.java b/core/src/main/java/eu/eudat/file/transformer/rda/Contact.java new file mode 100644 index 0000000..f8e9719 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Contact.java @@ -0,0 +1,144 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The DMP Contact Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "contact_id", + "mbox", + "name" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Contact implements Serializable +{ + + /** + * The Contact ID Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contact_id") + private ContactId contactId; + /** + * The Mailbox Schema + *

+ * Contact Person's E-mail address + * (Required) + * + */ + @JsonProperty("mbox") + @JsonPropertyDescription("Contact Person's E-mail address") + private String mbox; + /** + * The Name Schema + *

+ * Name of the contact person + * (Required) + * + */ + @JsonProperty("name") + @JsonPropertyDescription("Name of the contact person") + private String name; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -2062619884605400321L; + + /** + * The Contact ID Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contact_id") + public ContactId getContactId() { + return contactId; + } + + /** + * The Contact ID Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contact_id") + public void setContactId(ContactId contactId) { + this.contactId = contactId; + } + + /** + * The Mailbox Schema + *

+ * Contact Person's E-mail address + * (Required) + * + */ + @JsonProperty("mbox") + public String getMbox() { + return mbox; + } + + /** + * The Mailbox Schema + *

+ * Contact Person's E-mail address + * (Required) + * + */ + @JsonProperty("mbox") + public void setMbox(String mbox) { + this.mbox = mbox; + } + + /** + * The Name Schema + *

+ * Name of the contact person + * (Required) + * + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * The Name Schema + *

+ * Name of the contact person + * (Required) + * + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/ContactId.java b/core/src/main/java/eu/eudat/file/transformer/rda/ContactId.java new file mode 100644 index 0000000..91b4244 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/ContactId.java @@ -0,0 +1,150 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Contact ID Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "identifier", + "type" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ContactId implements Serializable +{ + + /** + * The DMP Contact Identifier Schema + *

+ * + * (Required) + * + */ + @JsonProperty("identifier") + private String identifier; + /** + * The DMP Contact Identifier Type Schema + *

+ * Identifier type. Allowed values: orcid, isni, openid, other + * (Required) + * + */ + @JsonProperty("type") + @JsonPropertyDescription("Identifier type. Allowed values: orcid, isni, openid, other") + private Type type; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -7066973565810615822L; + + /** + * The DMP Contact Identifier Schema + *

+ * + * (Required) + * + */ + @JsonProperty("identifier") + public String getIdentifier() { + return identifier; + } + + /** + * The DMP Contact Identifier Schema + *

+ * + * (Required) + * + */ + @JsonProperty("identifier") + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * The DMP Contact Identifier Type Schema + *

+ * Identifier type. Allowed values: orcid, isni, openid, other + * (Required) + * + */ + @JsonProperty("type") + public Type getType() { + return type; + } + + /** + * The DMP Contact Identifier Type Schema + *

+ * Identifier type. Allowed values: orcid, isni, openid, other + * (Required) + * + */ + @JsonProperty("type") + public void setType(Type type) { + this.type = type; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Type { + + ORCID("orcid"), + ISNI("isni"), + OPENID("openid"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Type fromValue(String value) { + Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Contributor.java b/core/src/main/java/eu/eudat/file/transformer/rda/Contributor.java new file mode 100644 index 0000000..48773ae --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Contributor.java @@ -0,0 +1,180 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +/** + * The Contributor Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "contributor_id", + "mbox", + "name", + "role" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Contributor implements Serializable +{ + + /** + * The Contributor_id Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contributor_id") + private ContributorId contributorId; + /** + * The Contributor Mailbox Schema + *

+ * Contributor Mail address + * + */ + @JsonProperty("mbox") + @JsonPropertyDescription("Contributor Mail address") + private String mbox; + /** + * The Name Schema + *

+ * Name of the contributor + * (Required) + * + */ + @JsonProperty("name") + @JsonPropertyDescription("Name of the contributor") + private String name; + /** + * The Role Schema + *

+ * Type of contributor + * (Required) + * + */ + @JsonProperty("role") + @JsonDeserialize(as = java.util.LinkedHashSet.class) + @JsonPropertyDescription("Type of contributor") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Set role = null; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 3452606902359513114L; + + /** + * The Contributor_id Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contributor_id") + public ContributorId getContributorId() { + return contributorId; + } + + /** + * The Contributor_id Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contributor_id") + public void setContributorId(ContributorId contributorId) { + this.contributorId = contributorId; + } + + /** + * The Contributor Mailbox Schema + *

+ * Contributor Mail address + * + */ + @JsonProperty("mbox") + public String getMbox() { + return mbox; + } + + /** + * The Contributor Mailbox Schema + *

+ * Contributor Mail address + * + */ + @JsonProperty("mbox") + public void setMbox(String mbox) { + this.mbox = mbox; + } + + /** + * The Name Schema + *

+ * Name of the contributor + * (Required) + * + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * The Name Schema + *

+ * Name of the contributor + * (Required) + * + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + /** + * The Role Schema + *

+ * Type of contributor + * (Required) + * + */ + @JsonProperty("role") + public Set getRole() { + return role; + } + + /** + * The Role Schema + *

+ * Type of contributor + * (Required) + * + */ + @JsonProperty("role") + public void setRole(Set role) { + this.role = role; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/ContributorId.java b/core/src/main/java/eu/eudat/file/transformer/rda/ContributorId.java new file mode 100644 index 0000000..07f0b17 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/ContributorId.java @@ -0,0 +1,151 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Contributor_id Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "identifier", + "type" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ContributorId implements Serializable +{ + + /** + * The Contributor Identifier Schema + *

+ * Identifier for a contact person + * (Required) + * + */ + @JsonProperty("identifier") + @JsonPropertyDescription("Identifier for a contact person") + private String identifier; + /** + * The Contributor Identifier Type Schema + *

+ * Identifier type. Allowed values: orcid, isni, openid, other + * (Required) + * + */ + @JsonProperty("type") + @JsonPropertyDescription("Identifier type. Allowed values: orcid, isni, openid, other") + private Type type; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 3089650417960767482L; + + /** + * The Contributor Identifier Schema + *

+ * Identifier for a contact person + * (Required) + * + */ + @JsonProperty("identifier") + public String getIdentifier() { + return identifier; + } + + /** + * The Contributor Identifier Schema + *

+ * Identifier for a contact person + * (Required) + * + */ + @JsonProperty("identifier") + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * The Contributor Identifier Type Schema + *

+ * Identifier type. Allowed values: orcid, isni, openid, other + * (Required) + * + */ + @JsonProperty("type") + public Type getType() { + return type; + } + + /** + * The Contributor Identifier Type Schema + *

+ * Identifier type. Allowed values: orcid, isni, openid, other + * (Required) + * + */ + @JsonProperty("type") + public void setType(Type type) { + this.type = type; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Type { + + ORCID("orcid"), + ISNI("isni"), + OPENID("openid"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Type fromValue(String value) { + Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Cost.java b/core/src/main/java/eu/eudat/file/transformer/rda/Cost.java new file mode 100644 index 0000000..4f07114 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Cost.java @@ -0,0 +1,370 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Cost Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "currency_code", + "description", + "title", + "value" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Cost implements Serializable +{ + + /** + * The Cost Currency Code Schema + *

+ * Allowed values defined by ISO 4217 + * + */ + @JsonProperty("currency_code") + @JsonPropertyDescription("Allowed values defined by ISO 4217") + private CurrencyCode currencyCode; + /** + * The Cost Description Schema + *

+ * Cost(s) Description + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Cost(s) Description") + private String description; + /** + * The Cost Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + @JsonPropertyDescription("Title") + private String title; + /** + * The Cost Value Schema + *

+ * Value + * + */ + @JsonProperty("value") + @JsonPropertyDescription("Value") + private Double value; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -322637784848035165L; + + /** + * The Cost Currency Code Schema + *

+ * Allowed values defined by ISO 4217 + * + */ + @JsonProperty("currency_code") + public CurrencyCode getCurrencyCode() { + return currencyCode; + } + + /** + * The Cost Currency Code Schema + *

+ * Allowed values defined by ISO 4217 + * + */ + @JsonProperty("currency_code") + public void setCurrencyCode(CurrencyCode currencyCode) { + this.currencyCode = currencyCode; + } + + /** + * The Cost Description Schema + *

+ * Cost(s) Description + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The Cost Description Schema + *

+ * Cost(s) Description + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The Cost Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + public String getTitle() { + return title; + } + + /** + * The Cost Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + public void setTitle(String title) { + this.title = title; + } + + /** + * The Cost Value Schema + *

+ * Value + * + */ + @JsonProperty("value") + public Double getValue() { + return value; + } + + /** + * The Cost Value Schema + *

+ * Value + * + */ + @JsonProperty("value") + public void setValue(Double value) { + this.value = value; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum CurrencyCode { + + AED("AED"), + AFN("AFN"), + ALL("ALL"), + AMD("AMD"), + ANG("ANG"), + AOA("AOA"), + ARS("ARS"), + AUD("AUD"), + AWG("AWG"), + AZN("AZN"), + BAM("BAM"), + BBD("BBD"), + BDT("BDT"), + BGN("BGN"), + BHD("BHD"), + BIF("BIF"), + BMD("BMD"), + BND("BND"), + BOB("BOB"), + BRL("BRL"), + BSD("BSD"), + BTN("BTN"), + BWP("BWP"), + BYN("BYN"), + BZD("BZD"), + CAD("CAD"), + CDF("CDF"), + CHF("CHF"), + CLP("CLP"), + CNY("CNY"), + COP("COP"), + CRC("CRC"), + CUC("CUC"), + CUP("CUP"), + CVE("CVE"), + CZK("CZK"), + DJF("DJF"), + DKK("DKK"), + DOP("DOP"), + DZD("DZD"), + EGP("EGP"), + ERN("ERN"), + ETB("ETB"), + EUR("EUR"), + FJD("FJD"), + FKP("FKP"), + GBP("GBP"), + GEL("GEL"), + GGP("GGP"), + GHS("GHS"), + GIP("GIP"), + GMD("GMD"), + GNF("GNF"), + GTQ("GTQ"), + GYD("GYD"), + HKD("HKD"), + HNL("HNL"), + HRK("HRK"), + HTG("HTG"), + HUF("HUF"), + IDR("IDR"), + ILS("ILS"), + IMP("IMP"), + INR("INR"), + IQD("IQD"), + IRR("IRR"), + ISK("ISK"), + JEP("JEP"), + JMD("JMD"), + JOD("JOD"), + JPY("JPY"), + KES("KES"), + KGS("KGS"), + KHR("KHR"), + KMF("KMF"), + KPW("KPW"), + KRW("KRW"), + KWD("KWD"), + KYD("KYD"), + KZT("KZT"), + LAK("LAK"), + LBP("LBP"), + LKR("LKR"), + LRD("LRD"), + LSL("LSL"), + LYD("LYD"), + MAD("MAD"), + MDL("MDL"), + MGA("MGA"), + MKD("MKD"), + MMK("MMK"), + MNT("MNT"), + MOP("MOP"), + MRU("MRU"), + MUR("MUR"), + MVR("MVR"), + MWK("MWK"), + MXN("MXN"), + MYR("MYR"), + MZN("MZN"), + NAD("NAD"), + NGN("NGN"), + NIO("NIO"), + NOK("NOK"), + NPR("NPR"), + NZD("NZD"), + OMR("OMR"), + PAB("PAB"), + PEN("PEN"), + PGK("PGK"), + PHP("PHP"), + PKR("PKR"), + PLN("PLN"), + PYG("PYG"), + QAR("QAR"), + RON("RON"), + RSD("RSD"), + RUB("RUB"), + RWF("RWF"), + SAR("SAR"), + SBD("SBD"), + SCR("SCR"), + SDG("SDG"), + SEK("SEK"), + SGD("SGD"), + SHP("SHP"), + SLL("SLL"), + SOS("SOS"), + SPL("SPL*"), + SRD("SRD"), + STN("STN"), + SVC("SVC"), + SYP("SYP"), + SZL("SZL"), + THB("THB"), + TJS("TJS"), + TMT("TMT"), + TND("TND"), + TOP("TOP"), + TRY("TRY"), + TTD("TTD"), + TVD("TVD"), + TWD("TWD"), + TZS("TZS"), + UAH("UAH"), + UGX("UGX"), + USD("USD"), + UYU("UYU"), + UZS("UZS"), + VEF("VEF"), + VND("VND"), + VUV("VUV"), + WST("WST"), + XAF("XAF"), + XCD("XCD"), + XDR("XDR"), + XOF("XOF"), + XPF("XPF"), + YER("YER"), + ZAR("ZAR"), + ZMW("ZMW"), + ZWD("ZWD"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (CurrencyCode c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private CurrencyCode(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static CurrencyCode fromValue(String value) { + CurrencyCode constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Dataset.java b/core/src/main/java/eu/eudat/file/transformer/rda/Dataset.java new file mode 100644 index 0000000..dda0dad --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Dataset.java @@ -0,0 +1,619 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * The Dataset Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "data_quality_assurance", + "dataset_id", + "description", + "distribution", + "issued", + "keyword", + "language", + "metadata", + "personal_data", + "preservation_statement", + "security_and_privacy", + "sensitive_data", + "technical_resource", + "title", + "type", + "additional_properties" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Dataset implements Serializable +{ + + /** + * The Data Quality Assurance Schema + *

+ * Data Quality Assurance + * + */ + @JsonProperty("data_quality_assurance") + @JsonPropertyDescription("Data Quality Assurance") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List dataQualityAssurance = null; + /** + * The Dataset ID Schema + *

+ * Dataset ID + * (Required) + * + */ + @JsonProperty("dataset_id") + @JsonPropertyDescription("Dataset ID") + private DatasetId datasetId; + /** + * The Dataset Description Schema + *

+ * Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file.") + private String description; + /** + * The Dataset Distribution Schema + *

+ * To provide technical information on a specific instance of data. + * + */ + @JsonProperty("distribution") + @JsonPropertyDescription("To provide technical information on a specific instance of data.") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List distribution = null; + /** + * The Dataset Date of Issue Schema + *

+ * Date of Issue + * + */ + @JsonProperty("issued") + @JsonPropertyDescription("Date of Issue") + private String issued; + /** + * The Dataset Keyword(s) Schema + *

+ * Keywords + * + */ + @JsonProperty("keyword") + @JsonPropertyDescription("Keywords") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List keyword = null; + /** + * The Dataset Language Schema + *

+ * Language of the dataset expressed using ISO 639-3. + * + */ + @JsonProperty("language") + @JsonPropertyDescription("Language of the dataset expressed using ISO 639-3.") + private Language language; + /** + * The Dataset Metadata Schema + *

+ * To describe metadata standards used. + * + */ + @JsonProperty("metadata") + @JsonPropertyDescription("To describe metadata standards used.") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List metadata = null; + /** + * The Dataset Personal Data Schema + *

+ * If any personal data is contained. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("personal_data") + @JsonPropertyDescription("If any personal data is contained. Allowed values: yes, no, unknown") + private PersonalData personalData; + /** + * The Dataset Preservation Statement Schema + *

+ * Preservation Statement + * + */ + @JsonProperty("preservation_statement") + @JsonPropertyDescription("Preservation Statement") + private String preservationStatement; + /** + * The Dataset Security and Policy Schema + *

+ * To list all issues and requirements related to security and privacy + * + */ + @JsonProperty("security_and_privacy") + @JsonPropertyDescription("To list all issues and requirements related to security and privacy") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List securityAndPrivacy = null; + /** + * The Dataset Sensitive Data Schema + *

+ * If any sensitive data is contained. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("sensitive_data") + @JsonPropertyDescription("If any sensitive data is contained. Allowed values: yes, no, unknown") + private SensitiveData sensitiveData; + /** + * The Dataset Technical Resource Schema + *

+ * To list all technical resources needed to implement a DMP + * + */ + @JsonProperty("technical_resource") + @JsonPropertyDescription("To list all technical resources needed to implement a DMP") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List technicalResource = null; + /** + * The Dataset Title Schema + *

+ * Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * (Required) + * + */ + @JsonProperty("title") + @JsonPropertyDescription("Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file.") + private String title; + /** + * The Dataset Type Schema + *

+ * If appropriate, type according to: DataCite and/or COAR dictionary. Otherwise use the common name for the type, e.g. raw data, software, survey, etc. https://schema.datacite.org/meta/kernel-4.1/doc/DataCite-MetadataKernel_v4.1.pdf http://vocabularies.coar-repositories.org/pubby/resource_type.html + * + */ + @JsonProperty("type") + @JsonPropertyDescription("If appropriate, type according to: DataCite and/or COAR dictionary. Otherwise use the common name for the type, e.g. raw data, software, survey, etc. https://schema.datacite.org/meta/kernel-4.1/doc/DataCite-MetadataKernel_v4.1.pdf http://vocabularies.coar-repositories.org/pubby/resource_type.html") + private String type; + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -6931119120629009399L; + + /** + * The Data Quality Assurance Schema + *

+ * Data Quality Assurance + * + */ + @JsonProperty("data_quality_assurance") + public List getDataQualityAssurance() { + return dataQualityAssurance; + } + + /** + * The Data Quality Assurance Schema + *

+ * Data Quality Assurance + * + */ + @JsonProperty("data_quality_assurance") + public void setDataQualityAssurance(List dataQualityAssurance) { + this.dataQualityAssurance = dataQualityAssurance; + } + + /** + * The Dataset ID Schema + *

+ * Dataset ID + * (Required) + * + */ + @JsonProperty("dataset_id") + public DatasetId getDatasetId() { + return datasetId; + } + + /** + * The Dataset ID Schema + *

+ * Dataset ID + * (Required) + * + */ + @JsonProperty("dataset_id") + public void setDatasetId(DatasetId datasetId) { + this.datasetId = datasetId; + } + + /** + * The Dataset Description Schema + *

+ * Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The Dataset Description Schema + *

+ * Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The Dataset Distribution Schema + *

+ * To provide technical information on a specific instance of data. + * + */ + @JsonProperty("distribution") + public List getDistribution() { + return distribution; + } + + /** + * The Dataset Distribution Schema + *

+ * To provide technical information on a specific instance of data. + * + */ + @JsonProperty("distribution") + public void setDistribution(List distribution) { + this.distribution = distribution; + } + + /** + * The Dataset Date of Issue Schema + *

+ * Date of Issue + * + */ + @JsonProperty("issued") + public String getIssued() { + return issued; + } + + /** + * The Dataset Date of Issue Schema + *

+ * Date of Issue + * + */ + @JsonProperty("issued") + public void setIssued(String issued) { + this.issued = issued; + } + + /** + * The Dataset Keyword(s) Schema + *

+ * Keywords + * + */ + @JsonProperty("keyword") + public List getKeyword() { + return keyword; + } + + /** + * The Dataset Keyword(s) Schema + *

+ * Keywords + * + */ + @JsonProperty("keyword") + public void setKeyword(List keyword) { + this.keyword = keyword; + } + + /** + * The Dataset Language Schema + *

+ * Language of the dataset expressed using ISO 639-3. + * + */ + @JsonProperty("language") + public Language getLanguage() { + return language; + } + + /** + * The Dataset Language Schema + *

+ * Language of the dataset expressed using ISO 639-3. + * + */ + @JsonProperty("language") + public void setLanguage(Language language) { + this.language = language; + } + + /** + * The Dataset Metadata Schema + *

+ * To describe metadata standards used. + * + */ + @JsonProperty("metadata") + public List getMetadata() { + return metadata; + } + + /** + * The Dataset Metadata Schema + *

+ * To describe metadata standards used. + * + */ + @JsonProperty("metadata") + public void setMetadata(List metadata) { + this.metadata = metadata; + } + + /** + * The Dataset Personal Data Schema + *

+ * If any personal data is contained. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("personal_data") + public PersonalData getPersonalData() { + return personalData; + } + + /** + * The Dataset Personal Data Schema + *

+ * If any personal data is contained. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("personal_data") + public void setPersonalData(PersonalData personalData) { + this.personalData = personalData; + } + + /** + * The Dataset Preservation Statement Schema + *

+ * Preservation Statement + * + */ + @JsonProperty("preservation_statement") + public String getPreservationStatement() { + return preservationStatement; + } + + /** + * The Dataset Preservation Statement Schema + *

+ * Preservation Statement + * + */ + @JsonProperty("preservation_statement") + public void setPreservationStatement(String preservationStatement) { + this.preservationStatement = preservationStatement; + } + + /** + * The Dataset Security and Policy Schema + *

+ * To list all issues and requirements related to security and privacy + * + */ + @JsonProperty("security_and_privacy") + public List getSecurityAndPrivacy() { + return securityAndPrivacy; + } + + /** + * The Dataset Security and Policy Schema + *

+ * To list all issues and requirements related to security and privacy + * + */ + @JsonProperty("security_and_privacy") + public void setSecurityAndPrivacy(List securityAndPrivacy) { + this.securityAndPrivacy = securityAndPrivacy; + } + + /** + * The Dataset Sensitive Data Schema + *

+ * If any sensitive data is contained. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("sensitive_data") + public SensitiveData getSensitiveData() { + return sensitiveData; + } + + /** + * The Dataset Sensitive Data Schema + *

+ * If any sensitive data is contained. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("sensitive_data") + public void setSensitiveData(SensitiveData sensitiveData) { + this.sensitiveData = sensitiveData; + } + + /** + * The Dataset Technical Resource Schema + *

+ * To list all technical resources needed to implement a DMP + * + */ + @JsonProperty("technical_resource") + public List getTechnicalResource() { + return technicalResource; + } + + /** + * The Dataset Technical Resource Schema + *

+ * To list all technical resources needed to implement a DMP + * + */ + @JsonProperty("technical_resource") + public void setTechnicalResource(List technicalResource) { + this.technicalResource = technicalResource; + } + + /** + * The Dataset Title Schema + *

+ * Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * (Required) + * + */ + @JsonProperty("title") + public String getTitle() { + return title; + } + + /** + * The Dataset Title Schema + *

+ * Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * (Required) + * + */ + @JsonProperty("title") + public void setTitle(String title) { + this.title = title; + } + + /** + * The Dataset Type Schema + *

+ * If appropriate, type according to: DataCite and/or COAR dictionary. Otherwise use the common name for the type, e.g. raw data, software, survey, etc. https://schema.datacite.org/meta/kernel-4.1/doc/DataCite-MetadataKernel_v4.1.pdf http://vocabularies.coar-repositories.org/pubby/resource_type.html + * + */ + @JsonProperty("type") + public String getType() { + return type; + } + + /** + * The Dataset Type Schema + *

+ * If appropriate, type according to: DataCite and/or COAR dictionary. Otherwise use the common name for the type, e.g. raw data, software, survey, etc. https://schema.datacite.org/meta/kernel-4.1/doc/DataCite-MetadataKernel_v4.1.pdf http://vocabularies.coar-repositories.org/pubby/resource_type.html + * + */ + @JsonProperty("type") + public void setType(String type) { + this.type = type; + } + + @JsonProperty("additional_properties") + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum PersonalData { + + YES("yes"), + NO("no"), + UNKNOWN("unknown"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (PersonalData c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private PersonalData(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static PersonalData fromValue(String value) { + PersonalData constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + + public enum SensitiveData { + + YES("yes"), + NO("no"), + UNKNOWN("unknown"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (SensitiveData c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private SensitiveData(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static SensitiveData fromValue(String value) { + SensitiveData constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/DatasetId.java b/core/src/main/java/eu/eudat/file/transformer/rda/DatasetId.java new file mode 100644 index 0000000..abf06d5 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/DatasetId.java @@ -0,0 +1,160 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Dataset ID Schema + *

+ * Dataset ID + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "identifier", + "type" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DatasetId implements Serializable +{ + + /** + * The Dataset Identifier Schema + *

+ * Identifier for a dataset + * (Required) + * + */ + @JsonProperty("identifier") + @JsonPropertyDescription("Identifier for a dataset") + private String identifier; + /** + * The Dataset Identifier Type Schema + *

+ * Dataset identifier type. Allowed values: handle, doi, ark, url, other + * (Required) + * + */ + @JsonProperty("type") + @JsonPropertyDescription("Dataset identifier type. Allowed values: handle, doi, ark, url, other") + private Type type; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -6295164005851378031L; + + public DatasetId() { + } + + public DatasetId(String identifier, Type type) { + this.identifier = identifier; + this.type = type; + } + + /** + * The Dataset Identifier Schema + *

+ * Identifier for a dataset + * (Required) + * + */ + @JsonProperty("identifier") + public String getIdentifier() { + return identifier; + } + + /** + * The Dataset Identifier Schema + *

+ * Identifier for a dataset + * (Required) + * + */ + @JsonProperty("identifier") + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * The Dataset Identifier Type Schema + *

+ * Dataset identifier type. Allowed values: handle, doi, ark, url, other + * (Required) + * + */ + @JsonProperty("type") + public Type getType() { + return type; + } + + /** + * The Dataset Identifier Type Schema + *

+ * Dataset identifier type. Allowed values: handle, doi, ark, url, other + * (Required) + * + */ + @JsonProperty("type") + public void setType(Type type) { + this.type = type; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Type { + + HANDLE("handle"), + DOI("doi"), + ARK("ark"), + URL("url"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Type fromValue(String value) { + Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Distribution.java b/core/src/main/java/eu/eudat/file/transformer/rda/Distribution.java new file mode 100644 index 0000000..3fd625b --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Distribution.java @@ -0,0 +1,410 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * The Dataset Distribution Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "access_url", + "available_until", + "byte_size", + "data_access", + "description", + "download_url", + "format", + "host", + "license", + "title", + "additional_properties" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Distribution implements Serializable +{ + + /** + * The Dataset Distribution Access URL Schema + *

+ * A URL of the resource that gives access to a distribution of the dataset. e.g. landing page. + * + */ + @JsonProperty("access_url") + @JsonPropertyDescription("A URL of the resource that gives access to a distribution of the dataset. e.g. landing page.") + private String accessUrl; + /** + * The Dataset Distribution Available Until Schema + *

+ * Indicates how long this distribution will be / should be available. + * + */ + @JsonProperty("available_until") + @JsonPropertyDescription("Indicates how long this distribution will be / should be available.") + private String availableUntil; + /** + * The Dataset Distribution Byte Size Schema + *

+ * Size in bytes. + * + */ + @JsonProperty("byte_size") + @JsonPropertyDescription("Size in bytes.") + private Integer byteSize; + /** + * The Dataset Distribution Data Access Schema + *

+ * Indicates access mode for data. Allowed values: open, shared, closed + * (Required) + * + */ + @JsonProperty("data_access") + @JsonPropertyDescription("Indicates access mode for data. Allowed values: open, shared, closed") + private DataAccess dataAccess; + /** + * The Dataset Distribution Description Schema + *

+ * Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file.") + private String description; + /** + * The Dataset Distribution Download URL Schema + *

+ * The URL of the downloadable file in a given format. E.g. CSV file or RDF file. + * + */ + @JsonProperty("download_url") + @JsonPropertyDescription("The URL of the downloadable file in a given format. E.g. CSV file or RDF file.") + private URI downloadUrl; + /** + * The Dataset Distribution Format Schema + *

+ * Format according to: https://www.iana.org/assignments/media-types/media-types.xhtml if appropriate, otherwise use the common name for this format. + * + */ + @JsonProperty("format") + @JsonPropertyDescription("Format according to: https://www.iana.org/assignments/media-types/media-types.xhtml if appropriate, otherwise use the common name for this format.") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List format = null; + /** + * The Dataset Distribution Host Schema + *

+ * To provide information on quality of service provided by infrastructure (e.g. repository) where data is stored. + * + */ + @JsonProperty("host") + @JsonPropertyDescription("To provide information on quality of service provided by infrastructure (e.g. repository) where data is stored.") + private Host host; + /** + * The Dataset Distribution License(s) Schema + *

+ * To list all licenses applied to a specific distribution of data. + * + */ + @JsonProperty("license") + @JsonPropertyDescription("To list all licenses applied to a specific distribution of data.") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List license = null; + /** + * The Dataset Distribution Title Schema + *

+ * Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * (Required) + * + */ + @JsonProperty("title") + @JsonPropertyDescription("Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file.") + private String title; + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -6018365280419917902L; + + /** + * The Dataset Distribution Access URL Schema + *

+ * A URL of the resource that gives access to a distribution of the dataset. e.g. landing page. + * + */ + @JsonProperty("access_url") + public String getAccessUrl() { + return accessUrl; + } + + /** + * The Dataset Distribution Access URL Schema + *

+ * A URL of the resource that gives access to a distribution of the dataset. e.g. landing page. + * + */ + @JsonProperty("access_url") + public void setAccessUrl(String accessUrl) { + this.accessUrl = accessUrl; + } + + /** + * The Dataset Distribution Available Until Schema + *

+ * Indicates how long this distribution will be / should be available. + * + */ + @JsonProperty("available_until") + public String getAvailableUntil() { + return availableUntil; + } + + /** + * The Dataset Distribution Available Until Schema + *

+ * Indicates how long this distribution will be / should be available. + * + */ + @JsonProperty("available_until") + public void setAvailableUntil(String availableUntil) { + this.availableUntil = availableUntil; + } + + /** + * The Dataset Distribution Byte Size Schema + *

+ * Size in bytes. + * + */ + @JsonProperty("byte_size") + public Integer getByteSize() { + return byteSize; + } + + /** + * The Dataset Distribution Byte Size Schema + *

+ * Size in bytes. + * + */ + @JsonProperty("byte_size") + public void setByteSize(Integer byteSize) { + this.byteSize = byteSize; + } + + /** + * The Dataset Distribution Data Access Schema + *

+ * Indicates access mode for data. Allowed values: open, shared, closed + * (Required) + * + */ + @JsonProperty("data_access") + public DataAccess getDataAccess() { + return dataAccess; + } + + /** + * The Dataset Distribution Data Access Schema + *

+ * Indicates access mode for data. Allowed values: open, shared, closed + * (Required) + * + */ + @JsonProperty("data_access") + public void setDataAccess(DataAccess dataAccess) { + this.dataAccess = dataAccess; + } + + /** + * The Dataset Distribution Description Schema + *

+ * Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The Dataset Distribution Description Schema + *

+ * Description is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The Dataset Distribution Download URL Schema + *

+ * The URL of the downloadable file in a given format. E.g. CSV file or RDF file. + * + */ + @JsonProperty("download_url") + public URI getDownloadUrl() { + return downloadUrl; + } + + /** + * The Dataset Distribution Download URL Schema + *

+ * The URL of the downloadable file in a given format. E.g. CSV file or RDF file. + * + */ + @JsonProperty("download_url") + public void setDownloadUrl(URI downloadUrl) { + this.downloadUrl = downloadUrl; + } + + /** + * The Dataset Distribution Format Schema + *

+ * Format according to: https://www.iana.org/assignments/media-types/media-types.xhtml if appropriate, otherwise use the common name for this format. + * + */ + @JsonProperty("format") + public List getFormat() { + return format; + } + + /** + * The Dataset Distribution Format Schema + *

+ * Format according to: https://www.iana.org/assignments/media-types/media-types.xhtml if appropriate, otherwise use the common name for this format. + * + */ + @JsonProperty("format") + public void setFormat(List format) { + this.format = format; + } + + /** + * The Dataset Distribution Host Schema + *

+ * To provide information on quality of service provided by infrastructure (e.g. repository) where data is stored. + * + */ + @JsonProperty("host") + public Host getHost() { + return host; + } + + /** + * The Dataset Distribution Host Schema + *

+ * To provide information on quality of service provided by infrastructure (e.g. repository) where data is stored. + * + */ + @JsonProperty("host") + public void setHost(Host host) { + this.host = host; + } + + /** + * The Dataset Distribution License(s) Schema + *

+ * To list all licenses applied to a specific distribution of data. + * + */ + @JsonProperty("license") + public List getLicense() { + return license; + } + + /** + * The Dataset Distribution License(s) Schema + *

+ * To list all licenses applied to a specific distribution of data. + * + */ + @JsonProperty("license") + public void setLicense(List license) { + this.license = license; + } + + /** + * The Dataset Distribution Title Schema + *

+ * Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * (Required) + * + */ + @JsonProperty("title") + public String getTitle() { + return title; + } + + /** + * The Dataset Distribution Title Schema + *

+ * Title is a property in both Dataset and Distribution, in compliance with W3C DCAT. In some cases these might be identical, but in most cases the Dataset represents a more abstract concept, while the distribution can point to a specific file. + * (Required) + * + */ + @JsonProperty("title") + public void setTitle(String title) { + this.title = title; + } + + @JsonProperty("additional_properties") + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum DataAccess { + + OPEN("open"), + SHARED("shared"), + CLOSED("closed"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (DataAccess c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private DataAccess(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static DataAccess fromValue(String value) { + DataAccess constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Dmp.java b/core/src/main/java/eu/eudat/file/transformer/rda/Dmp.java new file mode 100644 index 0000000..00a4869 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Dmp.java @@ -0,0 +1,551 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.net.URI; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * The DMP Schema + *

+ * + * + */ +@JsonIgnoreProperties(value = { "schema" }, ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "contact", + "contributor", + "cost", + "created", + "dataset", + "description", + "dmp_id", + "ethical_issues_description", + "ethical_issues_exist", + "ethical_issues_report", + "language", + "modified", + "project", + "title", + "additional_properties" +}) +public class Dmp implements Serializable +{ + + /** + * The DMP Contact Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contact") + private Contact contact; + /** + * The Contributor Schema + *

+ * + * + */ + @JsonProperty("contributor") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List contributor = null; + /** + * The Cost Schema + *

+ * + * + */ + @JsonProperty("cost") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List cost = null; + /** + * The DMP Creation Schema + *

+ * + * + */ + @JsonProperty("created") + @JsonPropertyDescription("") + private Instant created; + /** + * The Dataset Schema + *

+ * + * (Required) + * + */ + @JsonProperty("dataset") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List dataset = null; + /** + * The DMP Description Schema + *

+ * To provide any free-form text information on a DMP + * + */ + @JsonProperty("description") + @JsonPropertyDescription("To provide any free-form text information on a DMP") + private String description; + /** + * The DMP Identifier Schema + *

+ * Identifier for the DMP itself + * (Required) + * + */ + @JsonProperty("dmp_id") + @JsonPropertyDescription("Identifier for the DMP itself") + private DmpId dmpId; + /** + * The DMP Ethical Issues Description Schema + *

+ * To describe ethical issues directly in a DMP + * + */ + @JsonProperty("ethical_issues_description") + @JsonPropertyDescription("To describe ethical issues directly in a DMP") + private String ethicalIssuesDescription; + /** + * The DMP Ethical Issues Exist Schema + *

+ * To indicate whether there are ethical issues related to data that this DMP describes. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("ethical_issues_exist") + @JsonPropertyDescription("To indicate whether there are ethical issues related to data that this DMP describes. Allowed values: yes, no, unknown") + private EthicalIssuesExist ethicalIssuesExist; + /** + * The DMP Ethical Issues Report Schema + *

+ * To indicate where a protocol from a meeting with an ethical commitee can be found + * + */ + @JsonProperty("ethical_issues_report") + @JsonPropertyDescription("To indicate where a protocol from a meeting with an ethical commitee can be found") + private URI ethicalIssuesReport; + /** + * The DMP Language Schema + *

+ * Language of the DMP expressed using ISO 639-3. + * (Required) + * + */ + @JsonProperty("language") + @JsonPropertyDescription("Language of the DMP expressed using ISO 639-3.") + private Language language; + /** + * The DMP Modification Schema + *

+ * Must be set each time DMP is modified. Indicates DMP version. + * (Required) + * + */ + @JsonProperty("modified") + @JsonPropertyDescription("Must be set each time DMP is modified. Indicates DMP version.") + private Instant modified; + /** + * The DMP Project Schema + *

+ * Project related to a DMP + * + */ + @JsonProperty("project") + @JsonPropertyDescription("Project related to a DMP") + private List project = null; + /** + * The DMP Title Schema + *

+ * Title of a DMP + * (Required) + * + */ + @JsonProperty("title") + @JsonPropertyDescription("Title of a DMP") + private String title; + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 4599713332472772292L; + + /** + * The DMP Contact Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contact") + public Contact getContact() { + return contact; + } + + /** + * The DMP Contact Schema + *

+ * + * (Required) + * + */ + @JsonProperty("contact") + public void setContact(Contact contact) { + this.contact = contact; + } + + /** + * The Contributor Schema + *

+ * + * + */ + @JsonProperty("contributor") + public List getContributor() { + return contributor; + } + + /** + * The Contributor Schema + *

+ * + * + */ + @JsonProperty("contributor") + public void setContributor(List contributor) { + this.contributor = contributor; + } + + /** + * The Cost Schema + *

+ * + * + */ + @JsonProperty("cost") + public List getCost() { + return cost; + } + + /** + * The Cost Schema + *

+ * + * + */ + @JsonProperty("cost") + public void setCost(List cost) { + this.cost = cost; + } + + /** + * The DMP Creation Schema + *

+ * + * + */ + @JsonProperty("created") + public Instant getCreated() { + return created; + } + + /** + * The DMP Creation Schema + *

+ * + * + */ + @JsonProperty("created") + public void setCreated(Instant created) { + this.created = created; + } + + /** + * The Dataset Schema + *

+ * + * (Required) + * + */ + @JsonProperty("dataset") + public List getDataset() { + return dataset; + } + + /** + * The Dataset Schema + *

+ * + * (Required) + * + */ + @JsonProperty("dataset") + public void setDataset(List dataset) { + this.dataset = dataset; + } + + /** + * The DMP Description Schema + *

+ * To provide any free-form text information on a DMP + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The DMP Description Schema + *

+ * To provide any free-form text information on a DMP + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The DMP Identifier Schema + *

+ * Identifier for the DMP itself + * (Required) + * + */ + @JsonProperty("dmp_id") + public DmpId getDmpId() { + return dmpId; + } + + /** + * The DMP Identifier Schema + *

+ * Identifier for the DMP itself + * (Required) + * + */ + @JsonProperty("dmp_id") + public void setDmpId(DmpId dmpId) { + this.dmpId = dmpId; + } + + /** + * The DMP Ethical Issues Description Schema + *

+ * To describe ethical issues directly in a DMP + * + */ + @JsonProperty("ethical_issues_description") + public String getEthicalIssuesDescription() { + return ethicalIssuesDescription; + } + + /** + * The DMP Ethical Issues Description Schema + *

+ * To describe ethical issues directly in a DMP + * + */ + @JsonProperty("ethical_issues_description") + public void setEthicalIssuesDescription(String ethicalIssuesDescription) { + this.ethicalIssuesDescription = ethicalIssuesDescription; + } + + /** + * The DMP Ethical Issues Exist Schema + *

+ * To indicate whether there are ethical issues related to data that this DMP describes. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("ethical_issues_exist") + public EthicalIssuesExist getEthicalIssuesExist() { + return ethicalIssuesExist; + } + + /** + * The DMP Ethical Issues Exist Schema + *

+ * To indicate whether there are ethical issues related to data that this DMP describes. Allowed values: yes, no, unknown + * (Required) + * + */ + @JsonProperty("ethical_issues_exist") + public void setEthicalIssuesExist(EthicalIssuesExist ethicalIssuesExist) { + this.ethicalIssuesExist = ethicalIssuesExist; + } + + /** + * The DMP Ethical Issues Report Schema + *

+ * To indicate where a protocol from a meeting with an ethical commitee can be found + * + */ + @JsonProperty("ethical_issues_report") + public URI getEthicalIssuesReport() { + return ethicalIssuesReport; + } + + /** + * The DMP Ethical Issues Report Schema + *

+ * To indicate where a protocol from a meeting with an ethical commitee can be found + * + */ + @JsonProperty("ethical_issues_report") + public void setEthicalIssuesReport(URI ethicalIssuesReport) { + this.ethicalIssuesReport = ethicalIssuesReport; + } + + /** + * The DMP Language Schema + *

+ * Language of the DMP expressed using ISO 639-3. + * (Required) + * + */ + @JsonProperty("language") + public Language getLanguage() { + return language; + } + + /** + * The DMP Language Schema + *

+ * Language of the DMP expressed using ISO 639-3. + * (Required) + * + */ + @JsonProperty("language") + public void setLanguage(Language language) { + this.language = language; + } + + /** + * The DMP Modification Schema + *

+ * Must be set each time DMP is modified. Indicates DMP version. + * (Required) + * + */ + @JsonProperty("modified") + public Instant getModified() { + return modified; + } + + /** + * The DMP Modification Schema + *

+ * Must be set each time DMP is modified. Indicates DMP version. + * (Required) + * + */ + @JsonProperty("modified") + public void setModified(Instant modified) { + this.modified = modified; + } + + /** + * The DMP Project Schema + *

+ * Project related to a DMP + * + */ + @JsonProperty("project") + public List getProject() { + return project; + } + + /** + * The DMP Project Schema + *

+ * Project related to a DMP + * + */ + @JsonProperty("project") + public void setProject(List project) { + this.project = project; + } + + /** + * The DMP Title Schema + *

+ * Title of a DMP + * (Required) + * + */ + @JsonProperty("title") + public String getTitle() { + return title; + } + + /** + * The DMP Title Schema + *

+ * Title of a DMP + * (Required) + * + */ + @JsonProperty("title") + public void setTitle(String title) { + this.title = title; + } + + @JsonProperty("additional_properties") + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum EthicalIssuesExist { + + YES("yes"), + NO("no"), + UNKNOWN("unknown"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (EthicalIssuesExist c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private EthicalIssuesExist(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static EthicalIssuesExist fromValue(String value) { + EthicalIssuesExist constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/DmpId.java b/core/src/main/java/eu/eudat/file/transformer/rda/DmpId.java new file mode 100644 index 0000000..ad3f690 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/DmpId.java @@ -0,0 +1,152 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The DMP Identifier Schema + *

+ * Identifier for the DMP itself + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "identifier", + "type" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DmpId implements Serializable +{ + + /** + * The DMP Identifier Value Schema + *

+ * Identifier for a DMP + * (Required) + * + */ + @JsonProperty("identifier") + @JsonPropertyDescription("Identifier for a DMP") + private String identifier; + /** + * The DMP Identifier Type Schema + *

+ * The DMP Identifier Type. Allowed values: handle, doi, ark, url, other + * (Required) + * + */ + @JsonProperty("type") + @JsonPropertyDescription("The DMP Identifier Type. Allowed values: handle, doi, ark, url, other") + private Type type; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -6059908070202476841L; + + /** + * The DMP Identifier Value Schema + *

+ * Identifier for a DMP + * (Required) + * + */ + @JsonProperty("identifier") + public String getIdentifier() { + return identifier; + } + + /** + * The DMP Identifier Value Schema + *

+ * Identifier for a DMP + * (Required) + * + */ + @JsonProperty("identifier") + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * The DMP Identifier Type Schema + *

+ * The DMP Identifier Type. Allowed values: handle, doi, ark, url, other + * (Required) + * + */ + @JsonProperty("type") + public Type getType() { + return type; + } + + /** + * The DMP Identifier Type Schema + *

+ * The DMP Identifier Type. Allowed values: handle, doi, ark, url, other + * (Required) + * + */ + @JsonProperty("type") + public void setType(Type type) { + this.type = type; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Type { + + HANDLE("handle"), + DOI("doi"), + ARK("ark"), + URL("url"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Type fromValue(String value) { + Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/FunderId.java b/core/src/main/java/eu/eudat/file/transformer/rda/FunderId.java new file mode 100644 index 0000000..d2e2f50 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/FunderId.java @@ -0,0 +1,150 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Funder ID Schema + *

+ * Funder ID of the associated project + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "identifier", + "type" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class FunderId implements Serializable +{ + + /** + * The Funder ID Value Schema + *

+ * Funder ID, recommended to use CrossRef Funder Registry. See: https://www.crossref.org/services/funder-registry/ + * (Required) + * + */ + @JsonProperty("identifier") + @JsonPropertyDescription("Funder ID, recommended to use CrossRef Funder Registry. See: https://www.crossref.org/services/funder-registry/") + private String identifier; + /** + * The Funder ID Type Schema + *

+ * Identifier type. Allowed values: fundref, url, other + * (Required) + * + */ + @JsonProperty("type") + @JsonPropertyDescription("Identifier type. Allowed values: fundref, url, other") + private Type type; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 1783349151334366078L; + + /** + * The Funder ID Value Schema + *

+ * Funder ID, recommended to use CrossRef Funder Registry. See: https://www.crossref.org/services/funder-registry/ + * (Required) + * + */ + @JsonProperty("identifier") + public String getIdentifier() { + return identifier; + } + + /** + * The Funder ID Value Schema + *

+ * Funder ID, recommended to use CrossRef Funder Registry. See: https://www.crossref.org/services/funder-registry/ + * (Required) + * + */ + @JsonProperty("identifier") + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * The Funder ID Type Schema + *

+ * Identifier type. Allowed values: fundref, url, other + * (Required) + * + */ + @JsonProperty("type") + public Type getType() { + return type; + } + + /** + * The Funder ID Type Schema + *

+ * Identifier type. Allowed values: fundref, url, other + * (Required) + * + */ + @JsonProperty("type") + public void setType(Type type) { + this.type = type; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Type { + + FUNDREF("fundref"), + URL("url"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Type fromValue(String value) { + Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Funding.java b/core/src/main/java/eu/eudat/file/transformer/rda/Funding.java new file mode 100644 index 0000000..4789193 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Funding.java @@ -0,0 +1,183 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The DMP Project Funding Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "funder_id", + "funding_status", + "grant_id" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Funding implements Serializable +{ + + /** + * The Funder ID Schema + *

+ * Funder ID of the associated project + * (Required) + * + */ + @JsonProperty("funder_id") + @JsonPropertyDescription("Funder ID of the associated project") + private FunderId funderId; + /** + * The Funding Status Schema + *

+ * To express different phases of project lifecycle. Allowed values: planned, applied, granted, rejected + * + */ + @JsonProperty("funding_status") + @JsonPropertyDescription("To express different phases of project lifecycle. Allowed values: planned, applied, granted, rejected") + private FundingStatus fundingStatus; + /** + * The Funding Grant ID Schema + *

+ * Grant ID of the associated project + * (Required) + * + */ + @JsonProperty("grant_id") + @JsonPropertyDescription("Grant ID of the associated project") + private GrantId grantId; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 8962229321225336165L; + + /** + * The Funder ID Schema + *

+ * Funder ID of the associated project + * (Required) + * + */ + @JsonProperty("funder_id") + public FunderId getFunderId() { + return funderId; + } + + /** + * The Funder ID Schema + *

+ * Funder ID of the associated project + * (Required) + * + */ + @JsonProperty("funder_id") + public void setFunderId(FunderId funderId) { + this.funderId = funderId; + } + + /** + * The Funding Status Schema + *

+ * To express different phases of project lifecycle. Allowed values: planned, applied, granted, rejected + * + */ + @JsonProperty("funding_status") + public FundingStatus getFundingStatus() { + return fundingStatus; + } + + /** + * The Funding Status Schema + *

+ * To express different phases of project lifecycle. Allowed values: planned, applied, granted, rejected + * + */ + @JsonProperty("funding_status") + public void setFundingStatus(FundingStatus fundingStatus) { + this.fundingStatus = fundingStatus; + } + + /** + * The Funding Grant ID Schema + *

+ * Grant ID of the associated project + * (Required) + * + */ + @JsonProperty("grant_id") + public GrantId getGrantId() { + return grantId; + } + + /** + * The Funding Grant ID Schema + *

+ * Grant ID of the associated project + * (Required) + * + */ + @JsonProperty("grant_id") + public void setGrantId(GrantId grantId) { + this.grantId = grantId; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum FundingStatus { + + PLANNED("planned"), + APPLIED("applied"), + GRANTED("granted"), + REJECTED("rejected"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (FundingStatus c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private FundingStatus(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static FundingStatus fromValue(String value) { + FundingStatus constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/GrantId.java b/core/src/main/java/eu/eudat/file/transformer/rda/GrantId.java new file mode 100644 index 0000000..73cc0bb --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/GrantId.java @@ -0,0 +1,149 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Funding Grant ID Schema + *

+ * Grant ID of the associated project + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "identifier", + "type" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class GrantId implements Serializable +{ + + /** + * The Funding Grant ID Value Schema + *

+ * Grant ID + * (Required) + * + */ + @JsonProperty("identifier") + @JsonPropertyDescription("Grant ID") + private String identifier; + /** + * The Funding Grant ID Type Schema + *

+ * Identifier type. Allowed values: url, other + * (Required) + * + */ + @JsonProperty("type") + @JsonPropertyDescription("Identifier type. Allowed values: url, other") + private Type type; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -7738072672837592065L; + + /** + * The Funding Grant ID Value Schema + *

+ * Grant ID + * (Required) + * + */ + @JsonProperty("identifier") + public String getIdentifier() { + return identifier; + } + + /** + * The Funding Grant ID Value Schema + *

+ * Grant ID + * (Required) + * + */ + @JsonProperty("identifier") + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * The Funding Grant ID Type Schema + *

+ * Identifier type. Allowed values: url, other + * (Required) + * + */ + @JsonProperty("type") + public Type getType() { + return type; + } + + /** + * The Funding Grant ID Type Schema + *

+ * Identifier type. Allowed values: url, other + * (Required) + * + */ + @JsonProperty("type") + public void setType(Type type) { + this.type = type; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Type { + + URL("url"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Type fromValue(String value) { + Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Host.java b/core/src/main/java/eu/eudat/file/transformer/rda/Host.java new file mode 100644 index 0000000..f8865bf --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Host.java @@ -0,0 +1,772 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * The Dataset Distribution Host Schema + *

+ * To provide information on quality of service provided by infrastructure (e.g. repository) where data is stored. + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "availability", + "backup_frequency", + "backup_type", + "certified_with", + "description", + "geo_location", + "pid_system", + "storage_type", + "support_versioning", + "title", + "url" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Host implements Serializable +{ + + /** + * The Dataset Distribution Host Availability Schema + *

+ * Availability + * + */ + @JsonProperty("availability") + @JsonPropertyDescription("Availability") + private String availability; + /** + * The Dataset Distribution Host Backup Frequency Schema + *

+ * Backup Frequency + * + */ + @JsonProperty("backup_frequency") + @JsonPropertyDescription("Backup Frequency") + private String backupFrequency; + /** + * The Dataset Distribution Host Backup Type Schema + *

+ * Backup Type + * + */ + @JsonProperty("backup_type") + @JsonPropertyDescription("Backup Type") + private String backupType; + /** + * The Dataset Distribution Host Certification Type Schema + *

+ * Repository certified to a recognised standard. Allowed values: din31644, dini-zertifikat, dsa, iso16363, iso16919, trac, wds, coretrustseal + * + */ + @JsonProperty("certified_with") + @JsonPropertyDescription("Repository certified to a recognised standard. Allowed values: din31644, dini-zertifikat, dsa, iso16363, iso16919, trac, wds, coretrustseal") + private CertifiedWith certifiedWith; + /** + * The Dataset Distribution Host Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Description") + private String description; + /** + * The Dataset Distribution Host Geographical Location Schema + *

+ * Physical location of the data expressed using ISO 3166-1 country code. + * + */ + @JsonProperty("geo_location") + @JsonPropertyDescription("Physical location of the data expressed using ISO 3166-1 country code.") + private GeoLocation geoLocation; + /** + * The Dataset Distribution Host PID System Schema + *

+ * PID system(s). Allowed values: ark, arxiv, bibcode, doi, ean13, eissn, handle, igsn, isbn, issn, istc, lissn, lsid, pmid, purl, upc, url, urn, other + * + */ + @JsonProperty("pid_system") + @JsonPropertyDescription("PID system(s). Allowed values: ark, arxiv, bibcode, doi, ean13, eissn, handle, igsn, isbn, issn, istc, lissn, lsid, pmid, purl, upc, url, urn, other") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List pidSystem = null; + /** + * The Dataset Distribution Host Storage Type Schema + *

+ * The type of storage required + * + */ + @JsonProperty("storage_type") + @JsonPropertyDescription("The type of storage required") + private String storageType; + /** + * The Dataset Distribution Host Support Versioning Schema + *

+ * If host supports versioning. Allowed values: yes, no, unknown + * + */ + @JsonProperty("support_versioning") + @JsonPropertyDescription("If host supports versioning. Allowed values: yes, no, unknown") + private SupportVersioning supportVersioning; + /** + * The Dataset Distribution Host Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + @JsonPropertyDescription("Title") + private String title; + /** + * The Dataset Distribution Host Title Schema + *

+ * The URL of the system hosting a distribution of a dataset + * (Required) + * + */ + @JsonProperty("url") + @JsonPropertyDescription("The URL of the system hosting a distribution of a dataset") + private URI url; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 8564338806797654115L; + + /** + * The Dataset Distribution Host Availability Schema + *

+ * Availability + * + */ + @JsonProperty("availability") + public String getAvailability() { + return availability; + } + + /** + * The Dataset Distribution Host Availability Schema + *

+ * Availability + * + */ + @JsonProperty("availability") + public void setAvailability(String availability) { + this.availability = availability; + } + + /** + * The Dataset Distribution Host Backup Frequency Schema + *

+ * Backup Frequency + * + */ + @JsonProperty("backup_frequency") + public String getBackupFrequency() { + return backupFrequency; + } + + /** + * The Dataset Distribution Host Backup Frequency Schema + *

+ * Backup Frequency + * + */ + @JsonProperty("backup_frequency") + public void setBackupFrequency(String backupFrequency) { + this.backupFrequency = backupFrequency; + } + + /** + * The Dataset Distribution Host Backup Type Schema + *

+ * Backup Type + * + */ + @JsonProperty("backup_type") + public String getBackupType() { + return backupType; + } + + /** + * The Dataset Distribution Host Backup Type Schema + *

+ * Backup Type + * + */ + @JsonProperty("backup_type") + public void setBackupType(String backupType) { + this.backupType = backupType; + } + + /** + * The Dataset Distribution Host Certification Type Schema + *

+ * Repository certified to a recognised standard. Allowed values: din31644, dini-zertifikat, dsa, iso16363, iso16919, trac, wds, coretrustseal + * + */ + @JsonProperty("certified_with") + public CertifiedWith getCertifiedWith() { + return certifiedWith; + } + + /** + * The Dataset Distribution Host Certification Type Schema + *

+ * Repository certified to a recognised standard. Allowed values: din31644, dini-zertifikat, dsa, iso16363, iso16919, trac, wds, coretrustseal + * + */ + @JsonProperty("certified_with") + public void setCertifiedWith(CertifiedWith certifiedWith) { + this.certifiedWith = certifiedWith; + } + + /** + * The Dataset Distribution Host Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The Dataset Distribution Host Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The Dataset Distribution Host Geographical Location Schema + *

+ * Physical location of the data expressed using ISO 3166-1 country code. + * + */ + @JsonProperty("geo_location") + public GeoLocation getGeoLocation() { + return geoLocation; + } + + /** + * The Dataset Distribution Host Geographical Location Schema + *

+ * Physical location of the data expressed using ISO 3166-1 country code. + * + */ + @JsonProperty("geo_location") + public void setGeoLocation(GeoLocation geoLocation) { + this.geoLocation = geoLocation; + } + + /** + * The Dataset Distribution Host PID System Schema + *

+ * PID system(s). Allowed values: ark, arxiv, bibcode, doi, ean13, eissn, handle, igsn, isbn, issn, istc, lissn, lsid, pmid, purl, upc, url, urn, other + * + */ + @JsonProperty("pid_system") + public List getPidSystem() { + return pidSystem; + } + + /** + * The Dataset Distribution Host PID System Schema + *

+ * PID system(s). Allowed values: ark, arxiv, bibcode, doi, ean13, eissn, handle, igsn, isbn, issn, istc, lissn, lsid, pmid, purl, upc, url, urn, other + * + */ + @JsonProperty("pid_system") + public void setPidSystem(List pidSystem) { + this.pidSystem = pidSystem; + } + + /** + * The Dataset Distribution Host Storage Type Schema + *

+ * The type of storage required + * + */ + @JsonProperty("storage_type") + public String getStorageType() { + return storageType; + } + + /** + * The Dataset Distribution Host Storage Type Schema + *

+ * The type of storage required + * + */ + @JsonProperty("storage_type") + public void setStorageType(String storageType) { + this.storageType = storageType; + } + + /** + * The Dataset Distribution Host Support Versioning Schema + *

+ * If host supports versioning. Allowed values: yes, no, unknown + * + */ + @JsonProperty("support_versioning") + public SupportVersioning getSupportVersioning() { + return supportVersioning; + } + + /** + * The Dataset Distribution Host Support Versioning Schema + *

+ * If host supports versioning. Allowed values: yes, no, unknown + * + */ + @JsonProperty("support_versioning") + public void setSupportVersioning(SupportVersioning supportVersioning) { + this.supportVersioning = supportVersioning; + } + + /** + * The Dataset Distribution Host Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + public String getTitle() { + return title; + } + + /** + * The Dataset Distribution Host Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + public void setTitle(String title) { + this.title = title; + } + + /** + * The Dataset Distribution Host Title Schema + *

+ * The URL of the system hosting a distribution of a dataset + * (Required) + * + */ + @JsonProperty("url") + public URI getUrl() { + return url; + } + + /** + * The Dataset Distribution Host Title Schema + *

+ * The URL of the system hosting a distribution of a dataset + * (Required) + * + */ + @JsonProperty("url") + public void setUrl(URI url) { + this.url = url; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum CertifiedWith { + + DIN_31644("din31644"), + DINI_ZERTIFIKAT("dini-zertifikat"), + DSA("dsa"), + ISO_16363("iso16363"), + ISO_16919("iso16919"), + TRAC("trac"), + WDS("wds"), + CORETRUSTSEAL("coretrustseal"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (CertifiedWith c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private CertifiedWith(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static CertifiedWith fromValue(String value) { + CertifiedWith constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + + public enum GeoLocation { + + AD("AD"), + AE("AE"), + AF("AF"), + AG("AG"), + AI("AI"), + AL("AL"), + AM("AM"), + AO("AO"), + AQ("AQ"), + AR("AR"), + AS("AS"), + AT("AT"), + AU("AU"), + AW("AW"), + AX("AX"), + AZ("AZ"), + BA("BA"), + BB("BB"), + BD("BD"), + BE("BE"), + BF("BF"), + BG("BG"), + BH("BH"), + BI("BI"), + BJ("BJ"), + BL("BL"), + BM("BM"), + BN("BN"), + BO("BO"), + BQ("BQ"), + BR("BR"), + BS("BS"), + BT("BT"), + BV("BV"), + BW("BW"), + BY("BY"), + BZ("BZ"), + CA("CA"), + CC("CC"), + CD("CD"), + CF("CF"), + CG("CG"), + CH("CH"), + CI("CI"), + CK("CK"), + CL("CL"), + CM("CM"), + CN("CN"), + CO("CO"), + CR("CR"), + CU("CU"), + CV("CV"), + CW("CW"), + CX("CX"), + CY("CY"), + CZ("CZ"), + DE("DE"), + DJ("DJ"), + DK("DK"), + DM("DM"), + DO("DO"), + DZ("DZ"), + EC("EC"), + EE("EE"), + EG("EG"), + EH("EH"), + ER("ER"), + ES("ES"), + ET("ET"), + FI("FI"), + FJ("FJ"), + FK("FK"), + FM("FM"), + FO("FO"), + FR("FR"), + GA("GA"), + GB("GB"), + GD("GD"), + GE("GE"), + GF("GF"), + GG("GG"), + GH("GH"), + GI("GI"), + GL("GL"), + GM("GM"), + GN("GN"), + GP("GP"), + GQ("GQ"), + GR("GR"), + GS("GS"), + GT("GT"), + GU("GU"), + GW("GW"), + GY("GY"), + HK("HK"), + HM("HM"), + HN("HN"), + HR("HR"), + HT("HT"), + HU("HU"), + ID("ID"), + IE("IE"), + IL("IL"), + IM("IM"), + IN("IN"), + IO("IO"), + IQ("IQ"), + IR("IR"), + IS("IS"), + IT("IT"), + JE("JE"), + JM("JM"), + JO("JO"), + JP("JP"), + KE("KE"), + KG("KG"), + KH("KH"), + KI("KI"), + KM("KM"), + KN("KN"), + KP("KP"), + KR("KR"), + KW("KW"), + KY("KY"), + KZ("KZ"), + LA("LA"), + LB("LB"), + LC("LC"), + LI("LI"), + LK("LK"), + LR("LR"), + LS("LS"), + LT("LT"), + LU("LU"), + LV("LV"), + LY("LY"), + MA("MA"), + MC("MC"), + MD("MD"), + ME("ME"), + MF("MF"), + MG("MG"), + MH("MH"), + MK("MK"), + ML("ML"), + MM("MM"), + MN("MN"), + MO("MO"), + MP("MP"), + MQ("MQ"), + MR("MR"), + MS("MS"), + MT("MT"), + MU("MU"), + MV("MV"), + MW("MW"), + MX("MX"), + MY("MY"), + MZ("MZ"), + NA("NA"), + NC("NC"), + NE("NE"), + NF("NF"), + NG("NG"), + NI("NI"), + NL("NL"), + NO("NO"), + NP("NP"), + NR("NR"), + NU("NU"), + NZ("NZ"), + OM("OM"), + PA("PA"), + PE("PE"), + PF("PF"), + PG("PG"), + PH("PH"), + PK("PK"), + PL("PL"), + PM("PM"), + PN("PN"), + PR("PR"), + PS("PS"), + PT("PT"), + PW("PW"), + PY("PY"), + QA("QA"), + RE("RE"), + RO("RO"), + RS("RS"), + RU("RU"), + RW("RW"), + SA("SA"), + SB("SB"), + SC("SC"), + SD("SD"), + SE("SE"), + SG("SG"), + SH("SH"), + SI("SI"), + SJ("SJ"), + SK("SK"), + SL("SL"), + SM("SM"), + SN("SN"), + SO("SO"), + SR("SR"), + SS("SS"), + ST("ST"), + SV("SV"), + SX("SX"), + SY("SY"), + SZ("SZ"), + TC("TC"), + TD("TD"), + TF("TF"), + TG("TG"), + TH("TH"), + TJ("TJ"), + TK("TK"), + TL("TL"), + TM("TM"), + TN("TN"), + TO("TO"), + TR("TR"), + TT("TT"), + TV("TV"), + TW("TW"), + TZ("TZ"), + UA("UA"), + UG("UG"), + UM("UM"), + US("US"), + UY("UY"), + UZ("UZ"), + VA("VA"), + VC("VC"), + VE("VE"), + VG("VG"), + VI("VI"), + VN("VN"), + VU("VU"), + WF("WF"), + WS("WS"), + YE("YE"), + YT("YT"), + ZA("ZA"), + ZM("ZM"), + ZW("ZW"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (GeoLocation c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private GeoLocation(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static GeoLocation fromValue(String value) { + GeoLocation constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + + public enum SupportVersioning { + + YES("yes"), + NO("no"), + UNKNOWN("unknown"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (SupportVersioning c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private SupportVersioning(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static SupportVersioning fromValue(String value) { + SupportVersioning constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Language.java b/core/src/main/java/eu/eudat/file/transformer/rda/Language.java new file mode 100644 index 0000000..1bec5ff --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Language.java @@ -0,0 +1,229 @@ +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.HashMap; +import java.util.Map; + +public enum Language { + + AAR("aar"), + ABK("abk"), + AFR("afr"), + AKA("aka"), + AMH("amh"), + ARA("ara"), + ARG("arg"), + ASM("asm"), + AVA("ava"), + AVE("ave"), + AYM("aym"), + AZE("aze"), + BAK("bak"), + BAM("bam"), + BEL("bel"), + BEN("ben"), + BIH("bih"), + BIS("bis"), + BOD("bod"), + BOS("bos"), + BRE("bre"), + BUL("bul"), + CAT("cat"), + CES("ces"), + CHA("cha"), + CHE("che"), + CHU("chu"), + CHV("chv"), + COR("cor"), + COS("cos"), + CRE("cre"), + CYM("cym"), + DAN("dan"), + DEU("deu"), + DIV("div"), + DZO("dzo"), + ELL("ell"), + ENG("eng"), + EPO("epo"), + EST("est"), + EUS("eus"), + EWE("ewe"), + FAO("fao"), + FAS("fas"), + FIJ("fij"), + FIN("fin"), + FRA("fra"), + FRY("fry"), + FUL("ful"), + GLA("gla"), + GLE("gle"), + GLG("glg"), + GLV("glv"), + GRN("grn"), + GUJ("guj"), + HAT("hat"), + HAU("hau"), + HBS("hbs"), + HEB("heb"), + HER("her"), + HIN("hin"), + HMO("hmo"), + HRV("hrv"), + HUN("hun"), + HYE("hye"), + IBO("ibo"), + IDO("ido"), + III("iii"), + IKU("iku"), + ILE("ile"), + INA("ina"), + IND("ind"), + IPK("ipk"), + ISL("isl"), + ITA("ita"), + JAV("jav"), + JPN("jpn"), + KAL("kal"), + KAN("kan"), + KAS("kas"), + KAT("kat"), + KAU("kau"), + KAZ("kaz"), + KHM("khm"), + KIK("kik"), + KIN("kin"), + KIR("kir"), + KOM("kom"), + KON("kon"), + KOR("kor"), + KUA("kua"), + KUR("kur"), + LAO("lao"), + LAT("lat"), + LAV("lav"), + LIM("lim"), + LIN("lin"), + LIT("lit"), + LTZ("ltz"), + LUB("lub"), + LUG("lug"), + MAH("mah"), + MAL("mal"), + MAR("mar"), + MKD("mkd"), + MLG("mlg"), + MLT("mlt"), + MON("mon"), + MRI("mri"), + MSA("msa"), + MYA("mya"), + NAU("nau"), + NAV("nav"), + NBL("nbl"), + NDE("nde"), + NDO("ndo"), + NEP("nep"), + NLD("nld"), + NNO("nno"), + NOB("nob"), + NOR("nor"), + NYA("nya"), + OCI("oci"), + OJI("oji"), + ORI("ori"), + ORM("orm"), + OSS("oss"), + PAN("pan"), + PLI("pli"), + POL("pol"), + POR("por"), + PUS("pus"), + QUE("que"), + ROH("roh"), + RON("ron"), + RUN("run"), + RUS("rus"), + SAG("sag"), + SAN("san"), + SIN("sin"), + SLK("slk"), + SLV("slv"), + SME("sme"), + SMO("smo"), + SNA("sna"), + SND("snd"), + SOM("som"), + SOT("sot"), + SPA("spa"), + SQI("sqi"), + SRD("srd"), + SRP("srp"), + SSW("ssw"), + SUN("sun"), + SWA("swa"), + SWE("swe"), + TAH("tah"), + TAM("tam"), + TAT("tat"), + TEL("tel"), + TGK("tgk"), + TGL("tgl"), + THA("tha"), + TIR("tir"), + TON("ton"), + TSN("tsn"), + TSO("tso"), + TUK("tuk"), + TUR("tur"), + TWI("twi"), + UIG("uig"), + UKR("ukr"), + URD("urd"), + UZB("uzb"), + VEN("ven"), + VIE("vie"), + VOL("vol"), + WLN("wln"), + WOL("wol"), + XHO("xho"), + YID("yid"), + YOR("yor"), + ZHA("zha"), + ZHO("zho"), + ZUL("zul"); + private final String value; + private final static Map CONSTANTS = new HashMap<>(); + + static { + for (Language c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Language(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Language fromValue(String value) { + Language constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/License.java b/core/src/main/java/eu/eudat/file/transformer/rda/License.java new file mode 100644 index 0000000..d18ea78 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/License.java @@ -0,0 +1,111 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Dataset Distribution License Items + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "license_ref", + "start_date" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class License implements Serializable +{ + + /** + * The Dataset Distribution License Reference Schema + *

+ * Link to license document. + * (Required) + * + */ + @JsonProperty("license_ref") + @JsonPropertyDescription("Link to license document.") + private URI licenseRef; + /** + * The Dataset Distribution License Start Date Schema + *

+ * Starting date of license. If date is set in the future, it indicates embargo period. + * (Required) + * + */ + @JsonProperty("start_date") + @JsonPropertyDescription("Starting date of license. If date is set in the future, it indicates embargo period.") + private String startDate; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 4148207295817559010L; + + /** + * The Dataset Distribution License Reference Schema + *

+ * Link to license document. + * (Required) + * + */ + @JsonProperty("license_ref") + public URI getLicenseRef() { + return licenseRef; + } + + /** + * The Dataset Distribution License Reference Schema + *

+ * Link to license document. + * (Required) + * + */ + @JsonProperty("license_ref") + public void setLicenseRef(URI licenseRef) { + this.licenseRef = licenseRef; + } + + /** + * The Dataset Distribution License Start Date Schema + *

+ * Starting date of license. If date is set in the future, it indicates embargo period. + * (Required) + * + */ + @JsonProperty("start_date") + public String getStartDate() { + return startDate; + } + + /** + * The Dataset Distribution License Start Date Schema + *

+ * Starting date of license. If date is set in the future, it indicates embargo period. + * (Required) + * + */ + @JsonProperty("start_date") + public void setStartDate(String startDate) { + this.startDate = startDate; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/MetadataStandardId.java b/core/src/main/java/eu/eudat/file/transformer/rda/MetadataStandardId.java new file mode 100644 index 0000000..973b1f7 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/MetadataStandardId.java @@ -0,0 +1,149 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Dataset Metadata Standard ID Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "identifier", + "type" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class MetadataStandardId implements Serializable +{ + + /** + * The Dataset Metadata Standard Identifier Value Schema + *

+ * Identifier for the metadata standard used. + * (Required) + * + */ + @JsonProperty("identifier") + @JsonPropertyDescription("Identifier for the metadata standard used.") + private String identifier; + /** + * The Dataset Metadata Standard Identifier Type Schema + *

+ * Identifier type. Allowed values: url, other + * (Required) + * + */ + @JsonProperty("type") + @JsonPropertyDescription("Identifier type. Allowed values: url, other") + private Type type; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -7641042701935397947L; + + /** + * The Dataset Metadata Standard Identifier Value Schema + *

+ * Identifier for the metadata standard used. + * (Required) + * + */ + @JsonProperty("identifier") + public String getIdentifier() { + return identifier; + } + + /** + * The Dataset Metadata Standard Identifier Value Schema + *

+ * Identifier for the metadata standard used. + * (Required) + * + */ + @JsonProperty("identifier") + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * The Dataset Metadata Standard Identifier Type Schema + *

+ * Identifier type. Allowed values: url, other + * (Required) + * + */ + @JsonProperty("type") + public Type getType() { + return type; + } + + /** + * The Dataset Metadata Standard Identifier Type Schema + *

+ * Identifier type. Allowed values: url, other + * (Required) + * + */ + @JsonProperty("type") + public void setType(Type type) { + this.type = type; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Type { + + URL("url"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Type c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Type(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Type fromValue(String value) { + Type constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Metadatum.java b/core/src/main/java/eu/eudat/file/transformer/rda/Metadatum.java new file mode 100644 index 0000000..bf4867b --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Metadatum.java @@ -0,0 +1,364 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Dataset Metadata Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "description", + "language", + "metadata_standard_id", + "additional_properties" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Metadatum implements Serializable +{ + + /** + * The Dataset Metadata Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Description") + private String description; + /** + * The Dataset Metadata Language Schema + *

+ * Language of the metadata expressed using ISO 639-3. + * (Required) + * + */ + @JsonProperty("language") + @JsonPropertyDescription("Language of the metadata expressed using ISO 639-3.") + private Language language; + /** + * The Dataset Metadata Standard ID Schema + *

+ * + * (Required) + * + */ + @JsonProperty("metadata_standard_id") + private MetadataStandardId metadataStandardId; + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 6511312853153406190L; + + /** + * The Dataset Metadata Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The Dataset Metadata Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The Dataset Metadata Language Schema + *

+ * Language of the metadata expressed using ISO 639-3. + * (Required) + * + */ + @JsonProperty("language") + public Language getLanguage() { + return language; + } + + /** + * The Dataset Metadata Language Schema + *

+ * Language of the metadata expressed using ISO 639-3. + * (Required) + * + */ + @JsonProperty("language") + public void setLanguage(Language language) { + this.language = language; + } + + /** + * The Dataset Metadata Standard ID Schema + *

+ * + * (Required) + * + */ + @JsonProperty("metadata_standard_id") + public MetadataStandardId getMetadataStandardId() { + return metadataStandardId; + } + + /** + * The Dataset Metadata Standard ID Schema + *

+ * + * (Required) + * + */ + @JsonProperty("metadata_standard_id") + public void setMetadataStandardId(MetadataStandardId metadataStandardId) { + this.metadataStandardId = metadataStandardId; + } + + @JsonProperty("additional_properties") + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + + public enum Language { + + AAR("aar"), + ABK("abk"), + AFR("afr"), + AKA("aka"), + AMH("amh"), + ARA("ara"), + ARG("arg"), + ASM("asm"), + AVA("ava"), + AVE("ave"), + AYM("aym"), + AZE("aze"), + BAK("bak"), + BAM("bam"), + BEL("bel"), + BEN("ben"), + BIH("bih"), + BIS("bis"), + BOD("bod"), + BOS("bos"), + BRE("bre"), + BUL("bul"), + CAT("cat"), + CES("ces"), + CHA("cha"), + CHE("che"), + CHU("chu"), + CHV("chv"), + COR("cor"), + COS("cos"), + CRE("cre"), + CYM("cym"), + DAN("dan"), + DEU("deu"), + DIV("div"), + DZO("dzo"), + ELL("ell"), + ENG("eng"), + EPO("epo"), + EST("est"), + EUS("eus"), + EWE("ewe"), + FAO("fao"), + FAS("fas"), + FIJ("fij"), + FIN("fin"), + FRA("fra"), + FRY("fry"), + FUL("ful"), + GLA("gla"), + GLE("gle"), + GLG("glg"), + GLV("glv"), + GRN("grn"), + GUJ("guj"), + HAT("hat"), + HAU("hau"), + HBS("hbs"), + HEB("heb"), + HER("her"), + HIN("hin"), + HMO("hmo"), + HRV("hrv"), + HUN("hun"), + HYE("hye"), + IBO("ibo"), + IDO("ido"), + III("iii"), + IKU("iku"), + ILE("ile"), + INA("ina"), + IND("ind"), + IPK("ipk"), + ISL("isl"), + ITA("ita"), + JAV("jav"), + JPN("jpn"), + KAL("kal"), + KAN("kan"), + KAS("kas"), + KAT("kat"), + KAU("kau"), + KAZ("kaz"), + KHM("khm"), + KIK("kik"), + KIN("kin"), + KIR("kir"), + KOM("kom"), + KON("kon"), + KOR("kor"), + KUA("kua"), + KUR("kur"), + LAO("lao"), + LAT("lat"), + LAV("lav"), + LIM("lim"), + LIN("lin"), + LIT("lit"), + LTZ("ltz"), + LUB("lub"), + LUG("lug"), + MAH("mah"), + MAL("mal"), + MAR("mar"), + MKD("mkd"), + MLG("mlg"), + MLT("mlt"), + MON("mon"), + MRI("mri"), + MSA("msa"), + MYA("mya"), + NAU("nau"), + NAV("nav"), + NBL("nbl"), + NDE("nde"), + NDO("ndo"), + NEP("nep"), + NLD("nld"), + NNO("nno"), + NOB("nob"), + NOR("nor"), + NYA("nya"), + OCI("oci"), + OJI("oji"), + ORI("ori"), + ORM("orm"), + OSS("oss"), + PAN("pan"), + PLI("pli"), + POL("pol"), + POR("por"), + PUS("pus"), + QUE("que"), + ROH("roh"), + RON("ron"), + RUN("run"), + RUS("rus"), + SAG("sag"), + SAN("san"), + SIN("sin"), + SLK("slk"), + SLV("slv"), + SME("sme"), + SMO("smo"), + SNA("sna"), + SND("snd"), + SOM("som"), + SOT("sot"), + SPA("spa"), + SQI("sqi"), + SRD("srd"), + SRP("srp"), + SSW("ssw"), + SUN("sun"), + SWA("swa"), + SWE("swe"), + TAH("tah"), + TAM("tam"), + TAT("tat"), + TEL("tel"), + TGK("tgk"), + TGL("tgl"), + THA("tha"), + TIR("tir"), + TON("ton"), + TSN("tsn"), + TSO("tso"), + TUK("tuk"), + TUR("tur"), + TWI("twi"), + UIG("uig"), + UKR("ukr"), + URD("urd"), + UZB("uzb"), + VEN("ven"), + VIE("vie"), + VOL("vol"), + WLN("wln"), + WOL("wol"), + XHO("xho"), + YID("yid"), + YOR("yor"), + ZHA("zha"), + ZHO("zho"), + ZUL("zul"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (Language c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private Language(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static Language fromValue(String value) { + Language constant = CONSTANTS.get(value); + if (constant == null) { + return null; +// throw new IllegalArgumentException(value); + } else { + return constant; + } + } + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/PidSystem.java b/core/src/main/java/eu/eudat/file/transformer/rda/PidSystem.java new file mode 100644 index 0000000..6e2590d --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/PidSystem.java @@ -0,0 +1,64 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.HashMap; +import java.util.Map; + +public enum PidSystem { + + ARK("ark"), + ARXIV("arxiv"), + BIBCODE("bibcode"), + DOI("doi"), + EAN_13("ean13"), + EISSN("eissn"), + HANDLE("handle"), + IGSN("igsn"), + ISBN("isbn"), + ISSN("issn"), + ISTC("istc"), + LISSN("lissn"), + LSID("lsid"), + PMID("pmid"), + PURL("purl"), + UPC("upc"), + URL("url"), + URN("urn"), + OTHER("other"); + private final String value; + private final static Map CONSTANTS = new HashMap(); + + static { + for (PidSystem c: values()) { + CONSTANTS.put(c.value, c); + } + } + + private PidSystem(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } + + @JsonValue + public String value() { + return this.value; + } + + @JsonCreator + public static PidSystem fromValue(String value) { + PidSystem constant = CONSTANTS.get(value); + if (constant == null) { + throw new IllegalArgumentException(value); + } else { + return constant; + } + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/Project.java b/core/src/main/java/eu/eudat/file/transformer/rda/Project.java new file mode 100644 index 0000000..8b0655b --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/Project.java @@ -0,0 +1,211 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * The DMP Project Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "description", + "end", + "funding", + "start", + "title" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Project implements Serializable +{ + + /** + * The DMP Project Description Schema + *

+ * Project description + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Project description") + private String description; + /** + * The DMP Project End Date Schema + *

+ * Project end date + * (Required) + * + */ + @JsonProperty("end") + @JsonPropertyDescription("Project end date") + private String end; + /** + * The DMP Project Funding Schema + *

+ * Funding related with a project + * + */ + @JsonProperty("funding") + @JsonPropertyDescription("Funding related with a project") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List funding = null; + /** + * The DMP Project Start Date Schema + *

+ * Project start date + * (Required) + * + */ + @JsonProperty("start") + @JsonPropertyDescription("Project start date") + private String start; + /** + * The DMP Project Title Schema + *

+ * Project title + * (Required) + * + */ + @JsonProperty("title") + @JsonPropertyDescription("Project title") + private String title; + @JsonIgnore + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 1437619307195890472L; + + /** + * The DMP Project Description Schema + *

+ * Project description + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The DMP Project Description Schema + *

+ * Project description + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The DMP Project End Date Schema + *

+ * Project end date + * (Required) + * + */ + @JsonProperty("end") + public String getEnd() { + return end; + } + + /** + * The DMP Project End Date Schema + *

+ * Project end date + * (Required) + * + */ + @JsonProperty("end") + public void setEnd(String end) { + this.end = end; + } + + /** + * The DMP Project Funding Schema + *

+ * Funding related with a project + * + */ + @JsonProperty("funding") + public List getFunding() { + return funding; + } + + /** + * The DMP Project Funding Schema + *

+ * Funding related with a project + * + */ + @JsonProperty("funding") + public void setFunding(List funding) { + this.funding = funding; + } + + /** + * The DMP Project Start Date Schema + *

+ * Project start date + * (Required) + * + */ + @JsonProperty("start") + public String getStart() { + return start; + } + + /** + * The DMP Project Start Date Schema + *

+ * Project start date + * (Required) + * + */ + @JsonProperty("start") + public void setStart(String start) { + this.start = start; + } + + /** + * The DMP Project Title Schema + *

+ * Project title + * (Required) + * + */ + @JsonProperty("title") + public String getTitle() { + return title; + } + + /** + * The DMP Project Title Schema + *

+ * Project title + * (Required) + * + */ + @JsonProperty("title") + public void setTitle(String title) { + this.title = title; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/RDAModel.java b/core/src/main/java/eu/eudat/file/transformer/rda/RDAModel.java new file mode 100644 index 0000000..9891918 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/RDAModel.java @@ -0,0 +1,58 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; + + +/** + * RDA DMP Common Standard Schema + *

+ * JSON Schema for the RDA DMP Common Standard + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "dmp" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class RDAModel implements Serializable +{ + + /** + * The DMP Schema + *

+ * + * (Required) + * + */ + @JsonProperty("dmp") + private Dmp dmp; + private final static long serialVersionUID = 7331666133368350998L; + + /** + * The DMP Schema + *

+ * + * (Required) + * + */ + @JsonProperty("dmp") + public Dmp getDmp() { + return dmp; + } + + /** + * The DMP Schema + *

+ * + * (Required) + * + */ + @JsonProperty("dmp") + public void setDmp(Dmp dmp) { + this.dmp = dmp; + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/SecurityAndPrivacy.java b/core/src/main/java/eu/eudat/file/transformer/rda/SecurityAndPrivacy.java new file mode 100644 index 0000000..115c9ab --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/SecurityAndPrivacy.java @@ -0,0 +1,107 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Dataset Security & Policy Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "description", + "title", + "additional_properties" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecurityAndPrivacy implements Serializable +{ + + /** + * The Dataset Security & Policy Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Description") + private String description; + /** + * The Dataset Security & Policy Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + @JsonPropertyDescription("Title") + private String title; + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = 7863747935827682977L; + + /** + * The Dataset Security & Policy Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The Dataset Security & Policy Description Schema + *

+ * Description + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The Dataset Security & Policy Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + public String getTitle() { + return title; + } + + /** + * The Dataset Security & Policy Title Schema + *

+ * Title + * (Required) + * + */ + @JsonProperty("title") + public void setTitle(String title) { + this.title = title; + } + + @JsonProperty("additional_properties") + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/TechnicalResource.java b/core/src/main/java/eu/eudat/file/transformer/rda/TechnicalResource.java new file mode 100644 index 0000000..d2d3b0a --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/TechnicalResource.java @@ -0,0 +1,107 @@ + +package eu.eudat.file.transformer.rda; + +import com.fasterxml.jackson.annotation.*; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + + +/** + * The Dataset Technical Resource Items Schema + *

+ * + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "description", + "name", + "additional_properties" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class TechnicalResource implements Serializable +{ + + /** + * The Dataset Technical Resource Description Schema + *

+ * Description of the technical resource + * + */ + @JsonProperty("description") + @JsonPropertyDescription("Description of the technical resource") + private String description; + /** + * The Dataset Technical Resource Name Schema + *

+ * Name of the technical resource + * (Required) + * + */ + @JsonProperty("name") + @JsonPropertyDescription("Name of the technical resource") + private String name; + @JsonProperty("additional_properties") + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map additionalProperties = new HashMap(); + private final static long serialVersionUID = -7451757227129483110L; + + /** + * The Dataset Technical Resource Description Schema + *

+ * Description of the technical resource + * + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * The Dataset Technical Resource Description Schema + *

+ * Description of the technical resource + * + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * The Dataset Technical Resource Name Schema + *

+ * Name of the technical resource + * (Required) + * + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * The Dataset Technical Resource Name Schema + *

+ * Name of the technical resource + * (Required) + * + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + @JsonProperty("additional_properties") + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonProperty("additional_properties") + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactIdRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactIdRDAMapper.java new file mode 100644 index 0000000..47fb00c --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactIdRDAMapper.java @@ -0,0 +1,20 @@ +package eu.eudat.file.transformer.rda.mapper; + + +import eu.eudat.file.transformer.rda.ContactId; + +import java.util.UUID; + +public class ContactIdRDAMapper { + + public static ContactId toRDA(UUID id) { + ContactId rda = new ContactId(); + rda.setIdentifier(id.toString()); + rda.setType(ContactId.Type.OTHER); + return rda; + } + + public static UUID toEntity(ContactId rda) { + return UUID.fromString(rda.getIdentifier()); + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactRDAMapper.java new file mode 100644 index 0000000..10aede9 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContactRDAMapper.java @@ -0,0 +1,39 @@ +package eu.eudat.file.transformer.rda.mapper; + +import eu.eudat.file.transformer.enums.ContactInfoType; +import eu.eudat.file.transformer.models.user.UserContactInfoFileTransformerModel; +import eu.eudat.file.transformer.models.user.UserFileTransformerModel; +import eu.eudat.file.transformer.rda.Contact; + +import java.util.List; + +public class ContactRDAMapper { + + public static Contact toRDA(UserFileTransformerModel creator) { + Contact rda = new Contact(); + if (creator.getName() == null) { + throw new IllegalArgumentException("Contact Name is missing"); + } + rda.setName(creator.getName()); + //TODO: GetEmail + UserContactInfoFileTransformerModel emailContact = creator.getContacts().stream().filter(userContactInfo -> userContactInfo.getType().equals(ContactInfoType.Email)).findFirst().orElse(null); + if (emailContact == null) { + throw new IllegalArgumentException("Contact Email is missing"); + } + rda.setMbox(emailContact.getValue()); + rda.setContactId(ContactIdRDAMapper.toRDA(creator.getId())); + return rda; + } + + public static UserFileTransformerModel toEntity(Contact rda) { + UserFileTransformerModel entity = new UserFileTransformerModel(); + entity.setId(ContactIdRDAMapper.toEntity(rda.getContactId())); + entity.setName(rda.getName()); + UserContactInfoFileTransformerModel emailContactInfo = new UserContactInfoFileTransformerModel(); + emailContactInfo.setType(ContactInfoType.Email); + emailContactInfo.setValue(rda.getMbox()); + entity.setContacts(List.of(emailContactInfo)); +// entity.setEmail(rda.getMbox());//TODO: GetEmail + return entity; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorIdRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorIdRDAMapper.java new file mode 100644 index 0000000..8f67795 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorIdRDAMapper.java @@ -0,0 +1,22 @@ +package eu.eudat.file.transformer.rda.mapper; + + +import eu.eudat.file.transformer.rda.ContributorId; + +public class ContributorIdRDAMapper { + + public static ContributorId toRDA(Object id) { + ContributorId rda = new ContributorId(); + String idParts[] = id.toString().split(":"); + String prefix = idParts.length > 1 ? idParts[0] : id.toString(); + if (prefix.equals("orcid")) { + String finalId = id.toString().replace(prefix + ":", ""); + rda.setIdentifier("http://orcid.org/" + finalId); + rda.setType(ContributorId.Type.ORCID); + } else { + rda.setIdentifier(id.toString()); + rda.setType(ContributorId.Type.OTHER); + } + return rda; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorRDAMapper.java new file mode 100644 index 0000000..488b07d --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ContributorRDAMapper.java @@ -0,0 +1,90 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.file.transformer.enums.ContactInfoType; +import eu.eudat.file.transformer.models.dmp.DmpUserFileTransformerModel; +import eu.eudat.file.transformer.models.reference.DefinitionFileTransformerModel; +import eu.eudat.file.transformer.models.reference.FieldFileTransformerModel; +import eu.eudat.file.transformer.models.reference.ReferenceFileTransformerModel; +import eu.eudat.file.transformer.models.user.UserContactInfoFileTransformerModel; +import eu.eudat.file.transformer.rda.Contributor; +import eu.eudat.file.transformer.rda.ContributorId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashSet; +import java.util.List; + +public class ContributorRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(ContributorRDAMapper.class); + + public static Contributor toRDA(DmpUserFileTransformerModel userDMP) { + Contributor rda = new Contributor(); + rda.setContributorId(ContributorIdRDAMapper.toRDA(userDMP.getUser().getId())); + if (userDMP.getUser().getName() == null) { + throw new IllegalArgumentException("Contributor Name is missing"); + } + rda.setName(userDMP.getUser().getName()); + UserContactInfoFileTransformerModel emailContact = userDMP.getUser().getContacts().stream().filter(userContactInfo -> userContactInfo.getType().equals(ContactInfoType.Email)).findFirst().orElse(null); + if (emailContact != null) { + rda.setMbox(emailContact.getValue()); + } + rda.setRole(new HashSet<>(List.of(userDMP.getRole().name()))); + return rda; + } + + public static Contributor toRDA(ReferenceFileTransformerModel researcher) { + Contributor rda = new Contributor(); + rda.setContributorId(ContributorIdRDAMapper.toRDA(researcher.getReference())); + rda.setName(researcher.getLabel()); + if (researcher.getDefinition() != null) { + FieldFileTransformerModel emailField = researcher.getDefinition().getFields().stream().filter(field -> field.getCode().equals("primaryEmail")).findFirst().orElse(null); + if (emailField != null) { + rda.setMbox(emailField.getValue()); + } + } +// rda.setRole(new HashSet<>(Arrays.asList(UserDMP.UserDMPRoles.fromInteger(userDMP.getRole()).name()))); + return rda; + } + + public static Contributor toRDA(String value) { + ObjectMapper mapper = new ObjectMapper(); + try { + ReferenceFileTransformerModel researcher = mapper.readValue(value, ReferenceFileTransformerModel.class); + return toRDA(researcher); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + return null; + } + + public static ReferenceFileTransformerModel toEntity(Contributor rda) { + ReferenceFileTransformerModel reference = new ReferenceFileTransformerModel(); + String referenceString; + if (rda.getContributorId() != null) { + if (rda.getContributorId().getType() == ContributorId.Type.ORCID) { + String id = rda.getContributorId().getIdentifier().replace("http://orcid.org/", ""); + referenceString = "orcid:" + id; + } else { + String idParts[] = rda.getContributorId().getIdentifier().split(":"); + if (idParts.length == 1) { + referenceString = "dmp:" + rda.getContributorId().getIdentifier(); + } else { + referenceString = rda.getContributorId().getIdentifier(); + } + } + reference.setReference(referenceString); + reference.setLabel(rda.getName()); + FieldFileTransformerModel field = new FieldFileTransformerModel(); + field.setCode("primaryEmail"); + field.setValue(rda.getMbox()); + reference.setDefinition(new DefinitionFileTransformerModel()); + reference.getDefinition().setFields(List.of(field)); + } else { + return null; + } + + return reference; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/CostRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/CostRDAMapper.java new file mode 100644 index 0000000..fedaf77 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/CostRDAMapper.java @@ -0,0 +1,114 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.Cost; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class CostRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(DatasetRDAMapper.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + public static Cost toRDA(Map cost) throws JsonProcessingException { + Cost rda = new Cost(); + Map code = mapper.readValue((String) cost.get("code"), HashMap.class); + rda.setCurrencyCode(Cost.CurrencyCode.fromValue((String) code.get("value"))); + rda.setDescription((String) cost.get("description")); + if (cost.get("title") == null) { + throw new IllegalArgumentException("Cost Title is missing"); + } + rda.setTitle((String) cost.get("title")); + rda.setValue(((Integer) cost.get("value")).doubleValue()); + return rda; + } + + public static List toRDAList(List nodes) throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + Map rdaMap = new HashMap<>(); + for(FieldFileTransformerModel node: nodes){ + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dmp.cost")).findFirst().orElse(""); + if (node.getData() == null) { + continue; + } + String rdaValue = node.getData().getValue(); + if(rdaValue == null || rdaValue.isEmpty()){ + continue; + } + String key = node.getNumbering(); + + if(!key.contains("mult")){ + key = "0"; + } + else{ + key = "" + key.charAt(4); + } + Cost rda; + if(rdaMap.containsKey(key)){ + rda = rdaMap.get(key); + } + else{ + rda = new Cost(); + rdaMap.put(key, rda); + } + if(rdaProperty.contains("value")){ + try { + rda.setValue(Double.valueOf(rdaValue)); + } + catch (NumberFormatException e) { + logger.warn("Dmp cost value " + rdaValue + " is not valid. Cost value will not be set."); + } + } + else if(rdaProperty.contains("currency_code")){ + try { + HashMap result = + new ObjectMapper().readValue(rdaValue, HashMap.class); + rda.setCurrencyCode(Cost.CurrencyCode.fromValue(result.get("value"))); + } + catch (Exception e) { + logger.warn("Dmp cost currency code is not valid and will not be set."); + } + } + else if(rdaProperty.contains("title")){ + Iterator iter = mapper.readTree(rdaValue).elements(); + StringBuilder title = new StringBuilder(); + while(iter.hasNext()){ + String next = iter.next().asText(); + if(!next.equals("Other")) { + title.append(next).append(", "); + } + } + if(title.length() > 2){ + rda.setTitle(title.substring(0, title.length() - 2)); + } + else{ + String t = rda.getTitle(); + if(t == null){ // only other as title + rda.setTitle(rdaValue); + } + else{ // option + other + rda.setTitle(t + ", " + rdaValue); + } + } + } + else if(rdaProperty.contains("description")){ + rda.setDescription(rdaValue); + } + } + List rdaList = rdaMap.values().stream() + .filter(cost -> cost.getTitle() != null) + .collect(Collectors.toList()); + return rdaList; + + } + +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetIdRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetIdRDAMapper.java new file mode 100644 index 0000000..569b035 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetIdRDAMapper.java @@ -0,0 +1,139 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.DatasetId; +import eu.eudat.file.transformer.utils.json.JsonSearcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DatasetIdRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(DatasetIdRDAMapper.class); + + /*public static DatasetId toRDA(UUID id) { + DatasetId rda = new DatasetId(); + rda.setIdentifier(id.toString()); + rda.setType(DatasetId.Type.OTHER); + + return rda; + }*/ + + public static DatasetId toRDA(List nodes) { + DatasetId data = new DatasetId(); + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dataset.dataset_id")).findFirst().orElse(""); + if (node.getData() == null) { + continue; + } + String rdaValue = node.getData().getValue(); + if(rdaValue == null || rdaValue.isEmpty()){ + continue; + } + + ObjectMapper mapper = new ObjectMapper(); + try { + Map values = mapper.readValue(rdaValue, HashMap.class); + if (!values.isEmpty()) { + values.entrySet().forEach(entry -> finalRDAMap(data, entry.getKey(), (String) entry.getValue())); + } else { + finalRDAMap(data, rdaProperty, rdaValue); + } + } catch (IOException e) { + logger.warn(e.getMessage() + ".Passing value as is"); + finalRDAMap(data, rdaProperty, rdaValue); + + } + + } + + if (data.getIdentifier() != null && data.getType() != null) { + return data; + } + return null; + } + + private static void finalRDAMap(DatasetId rda, String property, String value) { + if (value != null) { + for (DatasetIdProperties datasetIdProperties : DatasetIdProperties.values()) { + if (property.contains(datasetIdProperties.getName())) { + switch (datasetIdProperties) { + case IDENTIFIER: + rda.setIdentifier(value); + break; + case TYPE: + try { + rda.setType(DatasetId.Type.fromValue(value)); + } + catch (IllegalArgumentException e){ + logger.warn("Type " + value + " from semantic rda.dataset.dataset_id.type was not found. Setting type to OTHER."); + rda.setType(DatasetId.Type.OTHER); + } + break; + } + } + } + } + + + } + + //TODO +/* + public static List toProperties(DatasetId rda, JsonNode node) { + List properties = new ArrayList<>(); + + List idNodes = JsonSearcher.findNodes(node, "schematics", "rda.dataset.dataset_id"); + + for (JsonNode idNode: idNodes) { + for (DatasetIdProperties datasetIdProperties : DatasetIdProperties.values()) { + JsonNode schematics = idNode.get("schematics"); + if(schematics.isArray()){ + for(JsonNode schematic: schematics){ + if(schematic.asText().endsWith(datasetIdProperties.getName())){ + switch (datasetIdProperties) { + case IDENTIFIER: + Field field1 = new Field(); + field1.setKey(idNode.get("id").asText()); + field1.setValue(rda.getIdentifier()); + properties.add(field1); + break; + case TYPE: + Field field2 = new Field(); + field2.setKey(idNode.get("id").asText()); + field2.setValue(rda.getType().value()); + properties.add(field2); + break; + } + break; + } + } + } + } + } + return properties; + } +*/ + + private enum DatasetIdProperties { + IDENTIFIER("identifier"), + TYPE("type"); + + private final String name; + + DatasetIdProperties(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetRDAMapper.java new file mode 100644 index 0000000..53ca1ea --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DatasetRDAMapper.java @@ -0,0 +1,436 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import eu.eudat.file.transformer.models.description.DescriptionFileTransformerModel; +import eu.eudat.file.transformer.models.descriptiontemplate.DescriptionTemplateFileTransformerModel; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.SectionFileTransformerModel; +import eu.eudat.file.transformer.models.tag.TagFileTransformerModel; +import eu.eudat.file.transformer.rda.*; +import eu.eudat.file.transformer.utils.descriptionTemplate.TemplateFieldSearcher; +import eu.eudat.file.transformer.utils.json.JsonSearcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.net.URI; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +@Component +public class DatasetRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(DatasetRDAMapper.class); + private final ObjectMapper mapper; + + @Autowired + public DatasetRDAMapper() { + this.mapper = new ObjectMapper(); + } + + public Dataset toRDA(DescriptionFileTransformerModel descriptionEntity, Dmp dmp) { + Dataset rda = new Dataset(); +// rda.setDatasetId(DatasetIdRDAMapper.toRDA(dataset.getId())); + if (descriptionEntity.getLabel() == null) { + throw new IllegalArgumentException("Dataset Label is missing"); + } + Map templateIdsToValues = this.createFieldIdValueMap(descriptionEntity.getDescriptionTemplate()); + rda.setTitle(descriptionEntity.getLabel()); + rda.setDescription(descriptionEntity.getDescription()); + //rda.setAdditionalProperty("template", descriptionEntity.getDescriptionTemplate()); //TODO + try { + List idNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.dataset_id"); + if (!idNodes.isEmpty()) { + rda.setDatasetId(DatasetIdRDAMapper.toRDA(idNodes)); + } + if (rda.getDatasetId() == null) { + rda.setDatasetId(new DatasetId(descriptionEntity.getId().toString(), DatasetId.Type.OTHER)); + } + List typeNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.type"); + if (!typeNodes.isEmpty() && typeNodes.get(0).getData() != null && !typeNodes.get(0).getData().getValue().isEmpty()) { + rda.setType(typeNodes.get(0).getData().getValue()); + } else { + rda.setType("DMP Dataset"); + } + List languageNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.language"); + if (!languageNodes.isEmpty() && languageNodes.get(0).getData() != null && !languageNodes.get(0).getData().getValue().isEmpty()) { + String lang = languageNodes.get(0).getData().getValue(); + try { + rda.setLanguage(Language.fromValue(lang)); + } + catch (IllegalArgumentException e){ + //TODO + logger.warn("Language " + lang + " from semantic rda.dataset.language was not found. Setting '" + descriptionEntity.getDescriptionTemplate().getLanguage() +"' as language from the dataset profile."); + rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(descriptionEntity.getDescriptionTemplate().getLanguage())); + } + } else { + //TODO + rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(descriptionEntity.getDescriptionTemplate().getLanguage())); + } + List metadataNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.metadata"); + if (!metadataNodes.isEmpty()) { + rda.setMetadata(MetadataRDAMapper.toRDAList(metadataNodes)); + }else{ + rda.setMetadata(new ArrayList<>()); + } + List qaNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.data_quality_assurance"); + if (!qaNodes.isEmpty()) { + rda.setDataQualityAssurance(qaNodes.stream().filter(qaNode -> qaNode.getData() != null).map(qaNode -> qaNode.getData().getValue()).collect(Collectors.toList())); + for (int i = 0; i < qaNodes.size(); i++) { + rda.setAdditionalProperty("qaId" + (i + 1), qaNodes.get(i).getId()); + } + List qaList = new ArrayList<>(); + String qa; + for(FieldFileTransformerModel node: qaNodes){ + if (node.getData() == null) { + continue; + } + JsonNode valueNode = mapper.readTree(node.getData().getValue()); + if(valueNode.isArray()){ + Iterator iter = valueNode.elements(); + while(iter.hasNext()) { + qa = iter.next().asText(); + qaList.add(qa); + } + } + } + String data_quality; + for(FieldFileTransformerModel dqa: qaNodes){ + if (dqa.getData() == null) { + continue; + } + data_quality = dqa.getData().getValue(); + if(!data_quality.isEmpty()){ + qaList.add(data_quality); + rda.setAdditionalProperty("otherDQAID", dqa.getId()); + rda.setAdditionalProperty("otherDQA", data_quality); + break; + } + } + rda.setDataQualityAssurance(qaList); + }else{ + rda.setDataQualityAssurance(new ArrayList<>()); + } + List preservationNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.preservation_statement"); + if (!preservationNodes.isEmpty() && preservationNodes.get(0).getData() != null && !preservationNodes.get(0).getData().getValue().isEmpty()) { + rda.setPreservationStatement(preservationNodes.get(0).getData().getValue()); + } + List distributionNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.distribution"); + if (!distributionNodes.isEmpty()) { + rda.setDistribution(DistributionRDAMapper.toRDAList(distributionNodes)); + }else{ + rda.setDistribution(new ArrayList<>()); + } + List keywordNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.keyword"); + if (!keywordNodes.isEmpty()) { + rda.setKeyword(keywordNodes.stream().filter(keywordNode -> keywordNode.getData() != null).map(keywordNode -> { + try { + JsonNode value = mapper.readTree(keywordNode.getData().getValue()); + if (value.isArray()) { + return StreamSupport.stream(value.spliterator(), false).map(node -> KeywordRDAMapper.toRDA(node.toString())).flatMap(Collection::stream).collect(Collectors.toList()); + } else { + return KeywordRDAMapper.toRDA(keywordNode.getData().getValue()); + } + }catch (JsonProcessingException e) { + logger.error(e.getMessage(), e); + return null; + } + }).filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList())); + for (int i = 0; i < keywordNodes.size(); i++) { + rda.setAdditionalProperty("keyword" + (i + 1), keywordNodes.get(i).getId()); + } + } +// else if (apiContext.getOperationsContext().getElasticRepository().getDatasetRepository().exists()) { //TODO +// List tags = apiContext.getOperationsContext().getElasticRepository().getDatasetRepository().findDocument(descriptionEntity.getId().toString()).getTags().stream().map(Tag::getName).collect(Collectors.toList()); +// rda.setKeyword(tags); +// } + List personalDataNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.personal_data"); + if (!personalDataNodes.isEmpty()) { + try{ + rda.setPersonalData(personalDataNodes.stream().filter(personalDataNode -> personalDataNode.getData() != null).map(personalDataNode -> Dataset.PersonalData.fromValue(personalDataNode.getData().getValue())).findFirst().get()); + }catch(IllegalArgumentException e){ + rda.setPersonalData(Dataset.PersonalData.UNKNOWN); + } + } else { + rda.setPersonalData(Dataset.PersonalData.UNKNOWN); + } + List securityAndPrivacyNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.security_and_privacy"); + if (!securityAndPrivacyNodes.isEmpty()) { + rda.setSecurityAndPrivacy(SecurityAndPrivacyRDAMapper.toRDAList(securityAndPrivacyNodes)); + }else{ + rda.setSecurityAndPrivacy(new ArrayList<>()); + } + List sensitiveDataNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.sensitive_data"); + if (!sensitiveDataNodes.isEmpty()) { + try{ + rda.setSensitiveData(sensitiveDataNodes.stream().filter(sensitiveDataNode -> sensitiveDataNode.getData() != null).map(sensitiveDataNode -> Dataset.SensitiveData.fromValue(sensitiveDataNode.getData().getValue())).findFirst().get()); + }catch(IllegalArgumentException e){ + rda.setSensitiveData(Dataset.SensitiveData.UNKNOWN); + } + } else { + rda.setSensitiveData(Dataset.SensitiveData.UNKNOWN); + } + List technicalResourceNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.technical_resource"); + if (!technicalResourceNodes.isEmpty()) { + rda.setTechnicalResource(TechnicalResourceRDAMapper.toRDAList(technicalResourceNodes)); + }else{ + rda.setTechnicalResource(new ArrayList<>()); + } + List issuedNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dataset.issued"); + if (!issuedNodes.isEmpty() && issuedNodes.get(0).getData() != null && !issuedNodes.get(0).getData().getValue().isEmpty()) { + rda.setIssued(issuedNodes.get(0).getData().getValue()); + } + List contributorNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dmp.contributor"); + if (!contributorNodes.isEmpty()) { + dmp.getContributor().addAll(contributorNodes.stream().filter(contributorNode -> contributorNode.getData() != null).map(contributorNode -> { + try { + JsonNode value = mapper.readTree(contributorNode.getData().getValue()); + if (value.isArray()) { + return StreamSupport.stream(value.spliterator(), false).map(node -> ContributorRDAMapper.toRDA(node.asText())).collect(Collectors.toList()); + } else { + return Collections.singletonList(new Contributor()); + } + }catch (JsonProcessingException e) { + return null; + } + }).filter(Objects::nonNull).flatMap(Collection::stream).toList()); + dmp.setContributor(dmp.getContributor().stream().filter(contributor -> contributor.getContributorId() != null && contributor.getName() != null).collect(Collectors.toList())); + } + List costNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dmp.cost"); + if (!costNodes.isEmpty()) { + dmp.getCost().addAll(CostRDAMapper.toRDAList(costNodes)); + } + List ethicsNodes = TemplateFieldSearcher.searchFields(descriptionEntity.getDescriptionTemplate(), "schematics", "rda.dmp.ethical_issues"); + if (!ethicsNodes.isEmpty()) { + for(FieldFileTransformerModel node: ethicsNodes){ + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dmp.ethical_issues")).findFirst().orElse(""); + if (node.getData() == null) { + continue; + } + String rdaValue = node.getData().getValue(); + if(rdaValue == null || rdaValue.isEmpty()){ + continue; + } + if(rdaProperty.contains("exist")){ + try { + Dmp.EthicalIssuesExist exists = dmp.getEthicalIssuesExist(); + if(exists == null + || ((exists == Dmp.EthicalIssuesExist.NO || exists == Dmp.EthicalIssuesExist.UNKNOWN) && rdaValue.equals("yes")) + || (exists == Dmp.EthicalIssuesExist.YES && !(rdaValue.equals("no") || rdaValue.equals("unknown"))) + || (exists == Dmp.EthicalIssuesExist.UNKNOWN && rdaValue.equals("no"))){ + dmp.setEthicalIssuesExist(Dmp.EthicalIssuesExist.fromValue(rdaValue)); + } + }catch(IllegalArgumentException e){ + logger.warn(e.getLocalizedMessage() + ". Setting ethical_issues_exist to unknown"); + dmp.setEthicalIssuesExist(Dmp.EthicalIssuesExist.UNKNOWN); + } + } + else if(rdaProperty.contains("description")){ + if(dmp.getEthicalIssuesDescription() == null){ + dmp.setEthicalIssuesDescription(rdaValue); + } + else{ + dmp.setEthicalIssuesDescription(dmp.getEthicalIssuesDescription() + ", " + rdaValue); + } + } + else if(rdaProperty.contains("report")){ + try { + dmp.setEthicalIssuesReport(URI.create(rdaValue)); + } catch (IllegalArgumentException e) { + logger.warn(e.getLocalizedMessage() + ". Skipping url parsing"); + } + } + } + } + List foundNodes = Stream.of(typeNodes, languageNodes, metadataNodes, qaNodes, preservationNodes, distributionNodes, + keywordNodes, personalDataNodes, securityAndPrivacyNodes, sensitiveDataNodes, technicalResourceNodes).flatMap(Collection::stream).toList(); + templateIdsToValues.entrySet().forEach(entry -> { + boolean isFound = foundNodes.stream().anyMatch(node -> node.getId().equals(entry.getKey())); + if (!isFound && entry.getValue() != null && !entry.getValue().toString().isEmpty()) { + try { + Instant time = Instant.parse(entry.getValue().toString()); + rda.setAdditionalProperty(entry.getKey(), DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()).format(time)); + } catch (DateTimeParseException e) { + rda.setAdditionalProperty(entry.getKey(), entry.getValue()); + } + } + }); + + + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + + + return rda; + } + + + public DescriptionFileTransformerModel toEntity(Dataset rda, DescriptionTemplateFileTransformerModel defaultProfile) { + DescriptionFileTransformerModel entity = new DescriptionFileTransformerModel(); + entity.setLabel(rda.getTitle()); + entity.setDescription(rda.getDescription()); + /*try { + DescriptionTemplateEntity profile = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(rda.getAdditionalProperties().get("template").toString())); + //entity.setDescriptionTemplateId(profile.getId()); //TODO + }catch(Exception e) { + logger.warn(e.getMessage(), e);*/ + entity.setDescriptionTemplate(defaultProfile); //TODO +// } + try { +// PropertyDefini properties = new PropertyDefinition(); +// properties.setFields(new ArrayList<>()); + String datasetDescriptionJson = mapper.writeValueAsString(entity.getDescriptionTemplate()); + JsonNode datasetDescriptionObj = mapper.readTree(datasetDescriptionJson); + + List typeNodes = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "schematics", "rda.dataset.type"); + if (!typeNodes.isEmpty()) { + typeNodes.get(0).getData().setValue(rda.getType()); + } + + List languageNodes = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "schematics", "rda.dataset.language"); + if (!languageNodes.isEmpty() && rda.getLanguage() != null) { + languageNodes.get(0).getData().setValue(rda.getLanguage().value()); + } + + //TODO + /*if (rda.getMetadata() != null) { + properties.getFields().addAll(MetadataRDAMapper.toProperties(rda.getMetadata())); + }*/ + + //TODO + /*if (rda.getDatasetId() != null) { + properties.getFields().addAll(DatasetIdRDAMapper.toProperties(rda.getDatasetId(), datasetDescriptionObj)); + }*/ + + /*List qaIds = rda.getAdditionalProperties().entrySet().stream().filter(entry -> entry.getKey().startsWith("qaId")).map(entry -> entry.getValue().toString()).collect(Collectors.toList()); + for (int i = 0; i < qaIds.size(); i++) { + properties.put(qaIds.get(i), rda.getDataQualityAssurance().get(i)); + }*/ + List qaNodes = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "schematics", "rda.dataset.data_quality_assurance"); + if (!qaNodes.isEmpty() && rda.getDataQualityAssurance() != null && !rda.getDataQualityAssurance().isEmpty()) { + ObjectMapper m = new ObjectMapper(); + List qas = new ArrayList<>(rda.getDataQualityAssurance()); + if(!qas.isEmpty()){ + qaNodes.get(0).getData().setValue(mapper.writeValueAsString(qas)); + if(rda.getAdditionalProperties().containsKey("otherDQAID")){ + List subFields = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "id", (String) rda.getAdditionalProperties().get("otherDQAID")); + if (subFields != null && !subFields.isEmpty()) { + subFields.get(0).getData().setValue((String) rda.getAdditionalProperties().get("otherDQA")); + } + } + } + } + + List preservationNodes = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "schematics", "rda.dataset.preservation_statement"); + if (!preservationNodes.isEmpty()) { + preservationNodes.get(0).getData().setValue(rda.getPreservationStatement()); + } + + List issuedNodes = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "schematics", "rda.dataset.issued"); + if (!issuedNodes.isEmpty()) { + issuedNodes.get(0).getData().setValue(rda.getIssued()); + } + + //TODO + /*if (rda.getDistribution() != null && !rda.getDistribution().isEmpty()) { + properties.getFields().addAll(DistributionRDAMapper.toProperties(rda.getDistribution().get(0), datasetDescriptionObj)); + }*/ + + if (rda.getKeyword() != null) { + List keywordIds = rda.getAdditionalProperties().entrySet().stream().filter(entry -> entry.getKey().startsWith("keyword")).map(entry -> entry.getValue().toString()).collect(Collectors.toList()); + boolean takeAll = false; + if (keywordIds.size() < rda.getKeyword().size()) { + takeAll = true; + } + for (int i = 0; i < keywordIds.size(); i++) { + List tagField = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "id", keywordIds.get(i)); + if (takeAll) { + List tags = new ArrayList<>(); + for (String keyword : rda.getKeyword()) { + tags.add(mapper.writeValueAsString(toTagEntity(keyword))); + } + tagField.get(0).getData().setValue(String.valueOf(tags)); + } else { + tagField.get(0).getData().setValue(mapper.writeValueAsString(toTagEntity(rda.getKeyword().get(i)))); + } + /*properties.getFields().add(field); + Field field1 = new Field(); + field1.setKey(keywordIds.get(i)); + field1.setValue(rda.getKeyword().get(i)); + properties.getFields().add(field1);*/ + } + } + + List personalDataNodes = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "schematics", "rda.dataset.personal_data"); + if (!personalDataNodes.isEmpty()) { + personalDataNodes.get(0).getData().setValue(rda.getPersonalData().value()); + } + + //TODO + /*if (rda.getSecurityAndPrivacy() != null) { + properties.getFields().addAll(SecurityAndPrivacyRDAMapper.toProperties(rda.getSecurityAndPrivacy())); + }*/ + + List sensitiveDataNodes = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "schematics", "rda.dataset.sensitive_data"); + if (!sensitiveDataNodes.isEmpty()) { + sensitiveDataNodes.get(0).getData().setValue(rda.getSensitiveData().value()); + } + + //TODO + /*if (rda.getTechnicalResource() != null) { + properties.getFields().addAll(TechnicalResourceRDAMapper.toProperties(rda.getTechnicalResource())); + }*/ + + rda.getAdditionalProperties().entrySet().stream() + .filter(entry -> !entry.getKey().equals("template") && !entry.getKey().startsWith("qaId") && !entry.getKey().startsWith("keyword")) + .forEach(entry -> { + List field = TemplateFieldSearcher.searchFields(entity.getDescriptionTemplate(), "id", entry.getKey()); + field.get(0).getData().setValue((String) entry.getValue()); + }); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + + + return entity; + } + + private static TagFileTransformerModel toTagEntity(String name) { + TagFileTransformerModel tag = new TagFileTransformerModel(); + tag.setId(UUID.randomUUID()); + tag.setLabel(name); + return tag; + } + + private Map createFieldIdValueMap(DescriptionTemplateFileTransformerModel template) { + Map result = new HashMap<>(); + + template.getDefinition().getPages().forEach(page -> page.getSections().forEach(section -> result.putAll(createFieldIdValueMapFromSection(section)))); + + return result; + } + + private Map createFieldIdValueMapFromSection(SectionFileTransformerModel section) { + Map result = new HashMap<>(); + + if (section.getSections() != null && !section.getSections().isEmpty()) { + section.getSections().forEach(subSection -> result.putAll(createFieldIdValueMapFromSection(subSection))); + } + if (section.getFieldSets() != null && !section.getFieldSets().isEmpty()) { + section.getFieldSets().stream().filter(fieldSet -> fieldSet.getFields() != null && !fieldSet.getFields().isEmpty()) + .forEach(fieldSet -> fieldSet.getFields().stream().filter(field -> field.getData() != null).forEach(field -> result.put(field.getId(), field.getData().getValue()))); + } + + return result; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DistributionRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DistributionRDAMapper.java new file mode 100644 index 0000000..e7e6141 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DistributionRDAMapper.java @@ -0,0 +1,439 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.Distribution; +import eu.eudat.file.transformer.rda.License; +import eu.eudat.file.transformer.utils.json.JsonSearcher; +import eu.eudat.file.transformer.utils.string.MyStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.util.*; +import java.util.stream.Collectors; + +public class DistributionRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(DistributionRDAMapper.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + public static List toRDAList(List nodes) { + Map rdaMap = new HashMap<>(); + + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = getRdaDistributionProperty(node); + if(rdaProperty.isEmpty() || node.getData() == null){ + continue; + } + String rdaValue = node.getData().getValue(); + //if(rdaValue == null || rdaValue.isEmpty()){ + if(rdaValue == null || rdaValue.isEmpty()){ + continue; + } + String key = node.getNumbering(); + if(!key.contains("mult")){ + key = "0"; + } + else{ + key = "" + key.charAt(4); + } + Distribution rda; + if(rdaMap.containsKey(key)){ + rda = rdaMap.get(key); + } + else { + rda = new Distribution(); + rdaMap.put(key, rda); + } + /* Distribution rda = getRelative(rdaMap, node.get("numbering").asText()); + if (!rdaMap.containsValue(rda)) { + rdaMap.put(node.get("numbering").asText(), rda); + } */ + for (ExportPropertyName exportPropertyName : ExportPropertyName.values()) { + if (rdaProperty.contains(exportPropertyName.getName())) { + switch (exportPropertyName) { + case ACCESS_URL: + rda.setAccessUrl(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.ACCESS_URL.getName(), node.getId()); + break; + case AVAILABLE_UNTIL: + rda.setAvailableUntil(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.AVAILABLE_UNTIL.getName(), node.getId()); + break; + case DOWNLOAD_URL: + rda.setDownloadUrl(URI.create(rdaValue)); + rda.setAdditionalProperty(ImportPropertyName.DOWNLOAD_URL.getName(), node.getId()); + break; + case DESCRIPTION: + if(!rdaProperty.contains("host")) { + rda.setDescription(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.DESCRIPTION.getName(), node.getId()); + } + break; + case DATA_ACCESS: + try { + rda.setDataAccess(Distribution.DataAccess.fromValue(rdaValue)); + rda.setAdditionalProperty(ImportPropertyName.DATA_ACCESS.getName(), node.getId()); + } + catch (IllegalArgumentException e) { + logger.warn("Distribution data access " + rdaValue + " from semantic distribution.data_access is not valid. Data access will not be set set."); + } + break; + case BYTE_SIZE: + rda.setByteSize(Integer.parseInt(rdaValue)); + rda.setAdditionalProperty(ImportPropertyName.BYTE_SIZE.getName(), node.getId()); + break; + case LICENSE: + List licenseNodes = nodes.stream().filter(lnode -> { + //if(lnode.get("schematics").isArray()){ + for(String schematic: lnode.getSchematics()){ + if(schematic.startsWith("rda.dataset.distribution.license")){ + return true; + } + } + //} + return false; + }).collect(Collectors.toList()); + License license = LicenseRDAMapper.toRDA(licenseNodes); + rda.setLicense(license != null? Collections.singletonList(license): new ArrayList<>()); + break; + case FORMAT: + try { + JsonNode valueNode = mapper.readTree(node.getData().getValue()); + if(valueNode.isArray()){ + Iterator iter = valueNode.elements(); + List formats = new ArrayList<>(); + int i = 1; + while(iter.hasNext()) { + JsonNode current = iter.next(); + String format = current.toString(); + + Map result = mapper.readValue(format, HashMap.class); + format = result.get("label"); + formats.add(format); + rda.setAdditionalProperty("format" + i++, mapper.readTree(current.toString())); + + } + rda.setFormat(formats); + } + else{ + if(rda.getFormat() == null || rda.getFormat().isEmpty()){ + rda.setFormat(new ArrayList<>(Arrays.asList(rdaValue.replace(" ", "").split(",")))); + } + else{ + rda.getFormat().addAll(Arrays.asList(rdaValue.replace(" ", "").split(","))); + } + } + rda.setAdditionalProperty(ImportPropertyName.FORMAT.getName(), node.getId()); + } + catch(JsonProcessingException e){ + logger.warn(e.getMessage()); + } + break; + case TITLE: + if(!rdaProperty.contains("host")) { + rda.setTitle(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.TITLE.getName(), node.getId()); + } + break; + case HOST: + rda.setHost(HostRDAMapper.toRDA(nodes, node.getNumbering())); + break; + } + } + } + } + return rdaMap.values().stream() + .filter(distro -> distro.getTitle() != null).collect(Collectors.toList()); + } + + //TODO + /*public static List toProperties(List rdas) { + List properties = new ArrayList<>(); + + rdas.forEach(rda -> { + rda.getAdditionalProperties().entrySet().forEach(entry -> { + try { + Field field = new Field(); + field.setKey(entry.getValue().toString()); + ImportPropertyName importPropertyName = ImportPropertyName.fromString(entry.getKey()); + switch (importPropertyName) { + case ACCESS_URL: + field.setValue(rda.getAccessUrl()); + break; + case TITLE: + field.setValue(rda.getTitle()); + break; + case DESCRIPTION: + field.setValue(rda.getDescription()); + break; + case FORMAT: + field.setValue(rda.getFormat().get(0)); + break; + case BYTE_SIZE: + field.setValue(rda.getByteSize().toString()); + break; + case DATA_ACCESS: + field.setValue(rda.getDataAccess().value()); + break; + case DOWNLOAD_URL: + field.setValue(rda.getDownloadUrl().toString()); + break; + case AVAILABLE_UNTIL: + field.setValue(rda.getAvailableUntil()); + break; + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + + }); + if (rda.getHost() != null) { + properties.addAll(HostRDAMapper.toProperties(rda.getHost())); + } + if (rda.getLicense() != null && !rda.getLicense().isEmpty()) { + properties.addAll(LicenseRDAMapper.toProperties(rda.getLicense())); + } + }); + + return properties; + } + + public static List toProperties(Distribution rda, JsonNode root) { + List properties = new ArrayList<>(); + + List distributionNodes = JsonSearcher.findNodes(root, "schematics", "rda.dataset.distribution"); + + for (JsonNode distributionNode: distributionNodes) { + for (ExportPropertyName exportPropertyName: ExportPropertyName.values()) { + JsonNode schematics = distributionNode.get("schematics"); + if(schematics.isArray()){ + for(JsonNode schematic: schematics){ + Field field = new Field(); + field.setKey(distributionNode.get("id").asText()); + if(schematic.asText().contains(exportPropertyName.getName())){ + switch (exportPropertyName) { + case ACCESS_URL: + field.setValue(rda.getAccessUrl()); + break; + case DESCRIPTION: + field.setValue(rda.getDescription()); + break; + case TITLE: + field.setValue(rda.getTitle()); + break; + case AVAILABLE_UNTIL: + field.setValue(rda.getAvailableUntil()); + break; + case DOWNLOAD_URL: + if (rda.getDownloadUrl() != null) { + field.setValue(rda.getDownloadUrl().toString()); + } + break; + case DATA_ACCESS: + field.setValue(rda.getDataAccess().value()); + break; + case BYTE_SIZE: + if (rda.getByteSize() != null) { + field.setValue(rda.getByteSize().toString()); + } + break; + case FORMAT: + if (rda.getFormat() != null && !rda.getFormat().isEmpty()) { + String style = distributionNode.get("viewStyle").get("renderStyle").asText(); + if(style.equals("combobox")) { + if (distributionNode.get("data").get("type").asText().equals("autocomplete")) { + Map additionalProperties = rda.getAdditionalProperties(); + List standardFormats = new ArrayList<>(); + rda.getAdditionalProperties().forEach((key, value) -> { + try { + if (key.matches("format\\d+")) { + standardFormats.add(additionalProperties.get(key)); + Field field1 = new Field(); + field1.setKey(distributionNode.get("id").asText()); + field1.setValue(mapper.writeValueAsString(standardFormats)); + properties.add(field1); + } + } catch (JsonProcessingException e) { + logger.error(e.getMessage(), e); + } + }); + } + } + else if(style.equals("freetext")){ + field.setValue(String.join(", ", rda.getFormat())); + } + } + break; + case LICENSE: + if (rda.getLicense() != null && !rda.getLicense().isEmpty()) { + properties.addAll(LicenseRDAMapper.toProperties(rda.getLicense().get(0), root)); + } + break; + case HOST: + if (rda.getHost() != null) { + properties.addAll(HostRDAMapper.toProperties(rda.getHost())); + } + break; + } + if (field.getValue() != null) { + properties.add(field); + } + break; + } + } + } + } + } + + return properties; + }*/ + + public static Distribution toRDA(List nodes) { + Distribution rda = new Distribution(); + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = getRdaDistributionProperty(node); + if(rdaProperty.isEmpty()){ + continue; + } + String rdaValue = node.getData().getValue(); + for (ExportPropertyName exportPropertyName: ExportPropertyName.values()) { + if (rdaProperty.contains(exportPropertyName.getName())) { + switch (exportPropertyName) { + case ACCESS_URL: + rda.setAccessUrl(rdaValue); + break; + case DESCRIPTION: + rda.setDescription(rdaValue); + break; + case TITLE: + rda.setTitle(rdaValue); + break; + case AVAILABLE_UNTIL: + rda.setAvailableUntil(rdaValue); + break; + case DOWNLOAD_URL: + rda.setDownloadUrl(URI.create(rdaValue)); + break; + case DATA_ACCESS: + rda.setDataAccess(Distribution.DataAccess.fromValue(rdaValue)); + break; + case BYTE_SIZE: + rda.setByteSize(Integer.parseInt(rdaValue)); + break; + case FORMAT: + rda.setFormat(Collections.singletonList(rdaValue)); + break; + case LICENSE: + List licenseNodes = nodes.stream().filter(lnode -> lnode.getSchematics().stream().anyMatch(schematic -> schematic.startsWith("rda.dataset.distribution.license"))).collect(Collectors.toList()); + rda.setLicense(Collections.singletonList(LicenseRDAMapper.toRDA(licenseNodes))); + break; + case HOST: + List hostNodes = nodes.stream().filter(lnode -> lnode.getSchematics().stream().anyMatch(schematic -> schematic.startsWith("rda.dataset.distribution.host"))).collect(Collectors.toList()); + rda.setHost(HostRDAMapper.toRDA(hostNodes, "0")); + break; + } + } + } + /*if (rdaProperty.contains("access_url")) { + rda.setAccessUrl(rdaValue); + } else if (rdaProperty.contains("available_util")) { + rda.setAvailableUntil(rdaValue); + } else if (rdaProperty.contains("byte_size")) { + rda.setByteSize(Integer.parseInt(rdaValue)); + } else if (rdaProperty.contains("data_access")) { + rda.setDataAccess(Distribution.DataAccess.fromValue(rdaValue)); + } else if (rdaProperty.contains("description")) { + rda.setDescription(rdaValue); + } else if (rdaProperty.contains("download_url")) { + rda.setDownloadUrl(URI.create(rdaValue)); + } else if (rdaProperty.contains("format")) { + rda.setFormat(Collections.singletonList(rdaValue)); + } else if (rdaProperty.contains("host")) { +// rda.setHost(HostRDAMapper.toRDA(node)); + } else if (rdaProperty.contains("license")) { + rda.setLicense(Collections.singletonList(LicenseRDAMapper.toRDA(node))); + } else if (rdaProperty.contains("title")) { + rda.setTitle(rdaValue); + }*/ + + } + + if (rda.getTitle() == null) { + throw new IllegalArgumentException("Distribution title is missing"); + } + + if (rda.getDataAccess() == null) { + throw new IllegalArgumentException("Distribution Data Access is missing"); + } + + return rda; + } + + private static String getRdaDistributionProperty(FieldFileTransformerModel node) { + return node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dataset.distribution")).findFirst().orElse(""); + } + + private static Distribution getRelative( Map rdaMap, String numbering) { + return rdaMap.entrySet().stream().filter(entry -> MyStringUtils.getFirstDifference(entry.getKey(), numbering) > 0) + .max(Comparator.comparingInt(entry -> MyStringUtils.getFirstDifference(entry.getKey(), numbering))).map(Map.Entry::getValue).orElse(new Distribution()); + } + + private enum ExportPropertyName { + ACCESS_URL("access_url"), + AVAILABLE_UNTIL("available_until"), + BYTE_SIZE("byte_size"), + DATA_ACCESS("data_access"), + DESCRIPTION("description"), + DOWNLOAD_URL("download_url"), + FORMAT("format"), + HOST("host"), + LICENSE("license"), + TITLE("title"); + + private final String name; + + ExportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + private enum ImportPropertyName { + ACCESS_URL("accessurlId"), + AVAILABLE_UNTIL("availableUtilId"), + BYTE_SIZE("byteSizeId"), + DATA_ACCESS("dataAccessId"), + DESCRIPTION("descriptionId"), + DOWNLOAD_URL("downloadUrlId"), + FORMAT("formatId"), + /*HOST("host"), + LICENSE("license"),*/ + TITLE("titleId"); + + private final String name; + + ImportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public static ImportPropertyName fromString(String name) throws Exception { + for (ImportPropertyName importPropertyName: ImportPropertyName.values()) { + if (importPropertyName.getName().equals(name)) { + return importPropertyName; + } + } + throw new Exception("No name available"); + } + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpIdRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpIdRDAMapper.java new file mode 100644 index 0000000..a8574a2 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpIdRDAMapper.java @@ -0,0 +1,19 @@ +package eu.eudat.file.transformer.rda.mapper; + +import eu.eudat.file.transformer.rda.DmpId; + +import java.util.UUID; + +public class DmpIdRDAMapper { + + public static DmpId toRDA(Object id) { + DmpId rda = new DmpId(); + rda.setIdentifier(id.toString()); + if (id instanceof UUID) { + rda.setType(DmpId.Type.OTHER); + } else { + rda.setType(DmpId.Type.DOI); + } + return rda; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpRDAMapper.java new file mode 100644 index 0000000..a630b7c --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/DmpRDAMapper.java @@ -0,0 +1,209 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.file.transformer.enums.ReferenceType; +import eu.eudat.file.transformer.models.descriptiontemplate.DescriptionTemplateFileTransformerModel; +import eu.eudat.file.transformer.models.dmp.DmpFileTransformerModel; +import eu.eudat.file.transformer.models.dmp.DmpReferenceFileTransformerModel; +import eu.eudat.file.transformer.models.dmp.DmpUserFileTransformerModel; +import eu.eudat.file.transformer.models.entitydoi.EntityDoiFileTransformerModel; +import eu.eudat.file.transformer.models.reference.ReferenceFileTransformerModel; +import eu.eudat.file.transformer.models.user.UserFileTransformerModel; +import eu.eudat.file.transformer.rda.Dmp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.management.InvalidApplicationException; +import java.io.IOException; +import java.util.*; + +@Component +public class DmpRDAMapper { + + private static final Logger logger = LoggerFactory.getLogger(DmpRDAMapper.class); + + private DatasetRDAMapper datasetRDAMapper; + private final ObjectMapper mapper; + + + @Autowired + public DmpRDAMapper(DatasetRDAMapper datasetRDAMapper) throws IOException { + this.datasetRDAMapper = datasetRDAMapper; + this.mapper = new ObjectMapper(); + } + + public Dmp toRDA(DmpFileTransformerModel dmp) throws InvalidApplicationException, JsonProcessingException { + + List grants = new ArrayList<>(); + List researchers = new ArrayList<>(); + List organizations = new ArrayList<>(); + List funders = new ArrayList<>(); + List projects = new ArrayList<>(); + if (dmp.getDmpReferences() != null) { + grants = dmp.getDmpReferences().stream().map(DmpReferenceFileTransformerModel::getReference).filter(referenceFileModel -> referenceFileModel.getType().equals(ReferenceType.Grants)).toList(); + researchers = dmp.getDmpReferences().stream().map(DmpReferenceFileTransformerModel::getReference).filter(reference -> reference.getType().equals(ReferenceType.Researcher)).toList(); + organizations = dmp.getDmpReferences().stream().map(DmpReferenceFileTransformerModel::getReference).filter(referenceFileModel -> referenceFileModel.getType().equals(ReferenceType.Organizations)).toList(); + funders = dmp.getDmpReferences().stream().map(DmpReferenceFileTransformerModel::getReference).filter(referenceFileModel -> referenceFileModel.getType().equals(ReferenceType.Funder)).toList(); + projects = dmp.getDmpReferences().stream().map(DmpReferenceFileTransformerModel::getReference).filter(reference -> reference.getType().equals(ReferenceType.Project)).toList(); + } + + if (dmp.getDescriptions() == null || dmp.getDescriptions().isEmpty()) { //TODO + throw new IllegalArgumentException("DMP has no Datasets"); + } + Map extraProperties; + if (dmp.getProperties() == null) { + throw new IllegalArgumentException("DMP is missing language and contact properties"); + } else { + extraProperties = mapper.readValue(dmp.getProperties(), HashMap.class); + /*if (extraProperties.get("language") == null) { + throw new IllegalArgumentException("DMP must have it's language property defined"); + }*/ + if (extraProperties.get("contacts") == null) { + throw new IllegalArgumentException("DMP must have it's contact property defined"); + } + } + Dmp rda = new Dmp(); + if (dmp.getEntityDois() != null && !dmp.getEntityDois().isEmpty()) { + for(EntityDoiFileTransformerModel doi: dmp.getEntityDois()){ + if(doi.getRepositoryId().equals("Zenodo")){ + rda.setDmpId(DmpIdRDAMapper.toRDA(doi.getDoi())); + } + } + } else { + rda.setDmpId(DmpIdRDAMapper.toRDA(dmp.getId())); + } + if (dmp.getCreatedAt() == null) { + throw new IllegalArgumentException("DMP Created is missing"); + } + if (dmp.getUpdatedAt() == null) { + throw new IllegalArgumentException("DMP Modified is missing"); + } + if (dmp.getLabel() == null) { + throw new IllegalArgumentException("DMP Label is missing"); + } + rda.setCreated(dmp.getCreatedAt()); //TODO + rda.setDescription(dmp.getDescription()); + rda.setModified(dmp.getUpdatedAt()); + rda.setTitle(dmp.getLabel()); + rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(dmp.getLanguage() != null ? dmp.getLanguage() : "en")); + + if (!extraProperties.isEmpty()) { + if (extraProperties.get("ethicalIssues") != null) { + rda.setEthicalIssuesExist(Dmp.EthicalIssuesExist.fromValue(extraProperties.get("ethicalIssues").toString())); + } else { + rda.setEthicalIssuesExist(Dmp.EthicalIssuesExist.UNKNOWN); + } + + if (extraProperties.get("costs") != null) { + rda.setCost(new ArrayList<>()); + ((List) extraProperties.get("costs")).forEach(costl -> { + try { + rda.getCost().add(CostRDAMapper.toRDA((Map)costl)); + } catch (JsonProcessingException e) { + logger.error(e.getMessage(), e); + } + }); + } + + UUID contactId = UUID.fromString((String) ((List>) extraProperties.get("contacts")).get(0).get("userId")); + if (contactId != null) { + UserFileTransformerModel userContact = dmp.getDmpUsers().stream().map(DmpUserFileTransformerModel::getUser) + .filter(userFileModel -> userFileModel.getId().equals(contactId)) + .findFirst().orElse(null); + if (userContact != null) { + rda.setContact(ContactRDAMapper.toRDA(userContact)); + } + } + } + + /*UserInfo creator; + if (dmp.getCreator() != null) { + creator = dmp.getCreator(); + } else { + creator = dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).map(UserDMP::getUser).findFirst().orElse(new UserInfo()); + } + rda.setContact(ContactRDAMapper.toRDA(creator));*/ + rda.setContributor(new ArrayList<>()); + if (!researchers.isEmpty()) { + rda.getContributor().addAll(researchers.stream().map(ContributorRDAMapper::toRDA).toList()); + } + rda.getContributor().addAll(dmp.getDmpUsers().stream().map(ContributorRDAMapper::toRDA).toList()); + rda.setDataset(dmp.getDescriptions().stream().map(dataset -> datasetRDAMapper.toRDA(dataset, rda)).toList()); + if (!projects.isEmpty() && !grants.isEmpty() && !funders.isEmpty()) { + rda.setProject(List.of(ProjectRDAMapper.toRDA(projects.get(0), grants.get(0), funders.get(0)))); + } + rda.setAdditionalProperty("templates", dmp.getDescriptions().stream().map(descriptionFileTransformerModel -> descriptionFileTransformerModel.getDescriptionTemplate().getId().toString()).toList()); + return rda; + } + + public DmpFileTransformerModel toEntity(Dmp rda, List profiles) throws InvalidApplicationException, JsonProcessingException { + DmpFileTransformerModel entity = new DmpFileTransformerModel(); + entity.setLabel(rda.getTitle()); + /*if (rda.getDmpId().getType() == DmpId.Type.DOI) { //TODO + try { + //TODO: Find from doi = rda.getDmpId().getIdentifier() + EntityDoi doi = new EntityDoi(); + List dois = new ArrayList<>(); + dois.add(doi); + entity.setEntityDois(dois); + } + catch (NoResultException e) { + logger.warn("No entity doi: " + rda.getDmpId().getIdentifier() + " found in database. No dois are added to dmp."); + entity.setDois(new HashSet<>()); + } + }*/ + /*if (((List) rda.getAdditionalProperties().get("templates")) != null && !((List) rda.getAdditionalProperties().get("templates")).isEmpty() && entity.getId() != null) { + entity.setAssociatedDmps(((List) rda.getAdditionalProperties().get("templates")).stream().map(x -> { + try { + return this.getProfile(x, entity.getId()); + } catch (InvalidApplicationException e) { + throw new RuntimeException(e); + } + }).filter(Objects::nonNull).collect(Collectors.toSet())); + }*/ + /*if (entity.getAssociatedDmps() == null) { + entity.setAssociatedDmps(new HashSet<>()); + }*/ + /*if (profiles != null && entity.getId() != null) { + for (String profile : profiles) { + entity.getAssociatedDmps().add(this.getProfile(profile, entity.getId())); + } + }*/ + entity.setDmpReferences(new ArrayList<>()); + + if (rda.getContributor() != null && !rda.getContributor().isEmpty() && rda.getContributor().get(0).getContributorId() != null) { + entity.getDmpReferences().addAll(rda.getContributor().stream().filter(r -> r.getContributorId() != null).map(ContributorRDAMapper::toEntity) + .map(reference -> { + DmpReferenceFileTransformerModel dmpReference = new DmpReferenceFileTransformerModel(); + dmpReference.setReference(reference); + return dmpReference; + }).toList()); + } + entity.setCreatedAt(rda.getCreated()); + entity.setUpdatedAt(rda.getModified()); + entity.setDescription(rda.getDescription()); + entity.setDescriptions(rda.getDataset().stream().map(rda1 -> datasetRDAMapper.toEntity(rda1, profiles.get(0))).toList()); + if (!rda.getProject().isEmpty()) { + entity.getDmpReferences().addAll(ProjectRDAMapper.toEntity(rda.getProject().get(0)).stream() + .map(reference -> { + DmpReferenceFileTransformerModel dmpReference = new DmpReferenceFileTransformerModel(); + dmpReference.setReference(reference); + return dmpReference; + }).toList()); + } + + Map extraProperties = new HashMap<>(); + extraProperties.put("language", LanguageRDAMapper.mapRDAIsoToLanguageIso(rda.getLanguage())); + + entity.setProperties(mapper.writeValueAsString(extraProperties)); + + return entity; + } + +// private DmpDescriptionTemplateEntity getProfile(String descriptionTemplateId, UUID dmpId) throws InvalidApplicationException { +// return this.queryFactory.query(DmpDescriptionTemplateQuery.class).dmpIds(dmpId).descriptionTemplateIds(UUID.fromString(descriptionTemplateId)).first(); +// } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/FunderIdRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/FunderIdRDAMapper.java new file mode 100644 index 0000000..106415e --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/FunderIdRDAMapper.java @@ -0,0 +1,19 @@ +package eu.eudat.file.transformer.rda.mapper; + +import eu.eudat.file.transformer.rda.FunderId; + +import java.util.UUID; + +public class FunderIdRDAMapper { + + public static FunderId toRDA(Object id) { + FunderId rda = new FunderId(); + rda.setIdentifier(id.toString()); + if (id instanceof UUID) { + rda.setType(FunderId.Type.OTHER); + } else { + rda.setType(FunderId.Type.FUNDREF); + } + return rda; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/FundingRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/FundingRDAMapper.java new file mode 100644 index 0000000..cb7347c --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/FundingRDAMapper.java @@ -0,0 +1,48 @@ +package eu.eudat.file.transformer.rda.mapper; + +import eu.eudat.file.transformer.enums.ReferenceType; +import eu.eudat.file.transformer.models.reference.ReferenceFileTransformerModel; +import eu.eudat.file.transformer.rda.Funding; + +import java.util.ArrayList; +import java.util.List; + +public class FundingRDAMapper { + + public static Funding toRDA(ReferenceFileTransformerModel grant, ReferenceFileTransformerModel funder) { + Funding rda = new Funding(); + String referencePrefix; + String shortReference; + Integer prefixLength = 0; + if (funder.getReference() != null) { + referencePrefix = funder.getReference().split(":")[0]; + prefixLength = referencePrefix.length() == funder.getReference().length() ? referencePrefix.length() - 1 : referencePrefix.length(); + shortReference = funder.getReference().substring(prefixLength + 1); + rda.setFunderId(FunderIdRDAMapper.toRDA(shortReference)); + } else { + rda.setFunderId(FunderIdRDAMapper.toRDA(funder.getId())); + } + if (grant.getReference() != null) { + referencePrefix = grant.getReference().split(":")[0]; + prefixLength = referencePrefix.length() == grant.getReference().length() ? referencePrefix.length() - 1 : referencePrefix.length(); + shortReference = grant.getReference().substring(prefixLength + 1); + rda.setGrantId(GrantIdRDAMapper.toRDA(shortReference)); + } else { + rda.setGrantId(GrantIdRDAMapper.toRDA(grant.getId().toString())); + } + return rda; + } + + public static List toEntity(Funding rda) { + List references = new ArrayList<>(); + ReferenceFileTransformerModel funder = new ReferenceFileTransformerModel(); + funder.setType(ReferenceType.Funder); + funder.setReference(rda.getFunderId().getIdentifier()); + references.add(funder); + ReferenceFileTransformerModel grant = new ReferenceFileTransformerModel(); + grant.setType(ReferenceType.Grants); + grant.setReference(rda.getGrantId().getIdentifier()); + references.add(grant); + return references; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/GrantIdRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/GrantIdRDAMapper.java new file mode 100644 index 0000000..f5db567 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/GrantIdRDAMapper.java @@ -0,0 +1,13 @@ +package eu.eudat.file.transformer.rda.mapper; + +import eu.eudat.file.transformer.rda.GrantId; + +public class GrantIdRDAMapper { + + public static GrantId toRDA(String id) { + GrantId rda = new GrantId(); + rda.setIdentifier(id); + rda.setType(GrantId.Type.OTHER); + return rda; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/HostRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/HostRDAMapper.java new file mode 100644 index 0000000..85eec24 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/HostRDAMapper.java @@ -0,0 +1,262 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.Host; +import eu.eudat.file.transformer.rda.PidSystem; +import eu.eudat.file.transformer.utils.string.MyStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.util.*; +import java.util.stream.Collectors; + +public class HostRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(HostRDAMapper.class); + + public static Host toRDA(List nodes, String numbering) { + ObjectMapper mapper = new ObjectMapper(); + Host rda = new Host(); + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dataset.distribution.host")).findFirst().orElse(""); + if (rdaProperty.contains("host")) { + int firstDiff = MyStringUtils.getFirstDifference(numbering, node.getNumbering()); + if (firstDiff == -1 || firstDiff >= 2) { + if (node.getData() == null) { + continue; + } + String rdaValue = node.getData().getValue(); + if(rdaValue == null || rdaValue.isEmpty()){ + continue; + } + for (ExportPropertyName propertyName: ExportPropertyName.values()) { + if (rdaProperty.contains(propertyName.getName())) { + switch (propertyName) { + case AVAILABILITY: + rda.setAvailability(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.AVAILABILITY.getName(), node.getId()); + break; + case BACKUP_FREQUENCY: + rda.setBackupFrequency(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.BACKUP_FREQUENCY.getName(), node.getId()); + break; + case BACKUP_TYPE: + rda.setBackupType(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.BACKUP_TYPE.getName(), node.getId()); + break; + case CERTIFIED_WITH: + try { + rda.setCertifiedWith(Host.CertifiedWith.fromValue(rdaValue)); + rda.setAdditionalProperty(ImportPropertyName.CERTIFIED_WITH.getName(), node.getId()); + } + catch (IllegalArgumentException e) { + logger.warn("Distribution host certified with " + rdaValue + "from semantic distribution.host.certified_with is not valid. Certified_with will not be set set."); + } + break; + case DESCRIPTION: + rda.setDescription(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.DESCRIPTION.getName(), node.getId()); + break; + case GEO_LOCATION: + if (rdaValue.startsWith("{")) { + try { + rdaValue = mapper.readValue(rdaValue, Map.class).get("id").toString(); + } catch (JsonProcessingException e) { + logger.warn(e.getLocalizedMessage() + ". Try to pass value as is"); + } + } + try { + rda.setGeoLocation(Host.GeoLocation.fromValue(rdaValue)); + rda.setAdditionalProperty(ImportPropertyName.GEO_LOCATION.getName(), node.getId()); + } + catch (IllegalArgumentException e) { + logger.warn("Distribution host geo location " + rdaValue + "from semantic distribution.host.geo_location is not valid. Geo location will not be set set."); + } + break; + case PID_SYSTEM: + try{ + JsonNode valueNode = mapper.readTree(rdaValue); + Iterator iter = valueNode.elements(); + List pList = new ArrayList<>(); + while(iter.hasNext()) { + pList.add(iter.next().asText()); + } + List pidList; + if(pList.size() == 0){ + pidList = Arrays.stream(rdaValue.replaceAll("[\\[\"\\]]","").split(",")) + .map(PidSystem::fromValue).collect(Collectors.toList()); + } + else{ + pidList = pList.stream().map(PidSystem::fromValue).collect(Collectors.toList()); + } + rda.setPidSystem(pidList); + rda.setAdditionalProperty(ImportPropertyName.PID_SYSTEM.getName(), node.getId()); + } + catch (IllegalArgumentException e){ + rda.setPidSystem(new ArrayList<>()); + break; + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + break; + case STORAGE_TYPE: + rda.setStorageType(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.STORAGE_TYPE.getName(), node.getId()); + break; + case SUPPORT_VERSIONING: + try { + rda.setSupportVersioning(Host.SupportVersioning.fromValue(rdaValue)); + rda.setAdditionalProperty(ImportPropertyName.SUPPORT_VERSIONING.getName(), node.getId()); + } + catch (IllegalArgumentException e) { + logger.warn("Distribution host support versioning " + rdaValue + "from semantic distribution.host.support_versioning is not valid. Support versioning will not be set set."); + } + break; + case TITLE: + rda.setTitle(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.TITLE.getName(), node.getId()); + break; + case URL: + try { + rda.setUrl(URI.create(rdaValue)); + rda.setAdditionalProperty(ImportPropertyName.URL.getName(), node.getId()); + } catch (IllegalArgumentException e) { + logger.warn(e.getLocalizedMessage() + ". Skipping url parsing"); + } + break; + } + } + } + } + } + } + + if(rda.getTitle() == null || rda.getUrl() == null){ + return null; + } + + return rda; + } + + //TODO +/* + public static List toProperties(Host rda) { + List properties = new ArrayList<>(); + rda.getAdditionalProperties().entrySet().forEach(entry -> { + try { + ImportPropertyName importPropertyName = ImportPropertyName.fromString(entry.getKey()); + Field field = new Field(); + field.setKey(entry.getValue().toString()); + switch (importPropertyName) { + case AVAILABILITY: + field.setValue(rda.getAvailability()); + break; + case TITLE: + field.setValue(rda.getTitle()); + break; + case DESCRIPTION: + field.setValue(rda.getDescription()); + break; + case BACKUP_FREQUENCY: + field.setValue(rda.getBackupFrequency()); + break; + case BACKUP_TYPE: + field.setValue(rda.getBackupType()); + break; + case CERTIFIED_WITH: + field.setValue(rda.getCertifiedWith().value()); + break; + case GEO_LOCATION: + field.setValue(rda.getGeoLocation().value()); + break; + case PID_SYSTEM: + List pids = new ArrayList<>(); + ObjectMapper mapper = new ObjectMapper(); + for(PidSystem pid: rda.getPidSystem()){ + pids.add(pid.value()); + } + if(!pids.isEmpty()){ + field.setValue(mapper.writeValueAsString(pids)); + } + break; + case STORAGE_TYPE: + field.setValue(rda.getStorageType()); + break; + case SUPPORT_VERSIONING: + field.setValue(rda.getSupportVersioning().value()); + break; + case URL: + field.setValue(rda.getUrl().toString()); + break; + } + properties.add(field); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + + }); + + return properties; + } +*/ + + private enum ExportPropertyName { + AVAILABILITY("availability"), + BACKUP_FREQUENCY("backup_frequency"), + BACKUP_TYPE("backup_type"), + CERTIFIED_WITH("certified_with"), + DESCRIPTION("description"), + GEO_LOCATION("geo_location"), + PID_SYSTEM("pid_system"), + STORAGE_TYPE("storage_type"), + SUPPORT_VERSIONING("support_versioning"), + TITLE("title"), + URL("url"); + + private final String name; + + ExportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + private enum ImportPropertyName { + AVAILABILITY("availabilityId"), + BACKUP_FREQUENCY("backup_frequencyId"), + BACKUP_TYPE("backup_typeId"), + CERTIFIED_WITH("certified_withId"), + DESCRIPTION("descriptionId"), + GEO_LOCATION("geo_locationId"), + PID_SYSTEM("pid_systemId"), + STORAGE_TYPE("storage_typeId"), + SUPPORT_VERSIONING("support_versioningId"), + TITLE("titleId"), + URL("urlId"); + + private final String name; + + ImportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public static ImportPropertyName fromString(String name) throws Exception { + for (ImportPropertyName importPropertyName: ImportPropertyName.values()) { + if (importPropertyName.getName().equals(name)) { + return importPropertyName; + } + } + throw new Exception("No name available"); + } + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/KeywordRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/KeywordRDAMapper.java new file mode 100644 index 0000000..2eea7fd --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/KeywordRDAMapper.java @@ -0,0 +1,30 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.file.transformer.models.tag.TagFileTransformerModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class KeywordRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(KeywordRDAMapper.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + public static List toRDA(String value) { + if (!value.isEmpty() && !value.equals("null")) { + try { + TagFileTransformerModel tag = mapper.readValue(value, TagFileTransformerModel.class); + return new ArrayList<>(Collections.singletonList(tag.getLabel())); + } catch (JsonProcessingException e) { + logger.warn(e.getMessage() + ". Attempting to parse it as a String since its a new tag."); + return new ArrayList<>(Collections.singletonList(value)); + } + } + + return new ArrayList<>(); + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/LanguageRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/LanguageRDAMapper.java new file mode 100644 index 0000000..a23b0de --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/LanguageRDAMapper.java @@ -0,0 +1,45 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.file.transformer.rda.Language; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +public class LanguageRDAMapper { + private final static Map langMap = new HashMap<>(); + private static final Logger logger = LoggerFactory.getLogger(LanguageRDAMapper.class); + + static { + try { + ObjectMapper mapper = new ObjectMapper(); + InputStreamReader isr = new InputStreamReader(LanguageRDAMapper.class.getClassLoader().getResource("internal/rda-lang-map.json").openStream(), StandardCharsets.UTF_8); + langMap.putAll(mapper.readValue(isr, LinkedHashMap.class)); + isr.close(); + + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + + public static Language mapLanguageIsoToRDAIso(String code) { + return langMap.entrySet().stream().map(entry -> { + if (entry.getValue().toString().equals(code)) { + return Language.fromValue(entry.getKey()); + } else { + return null; + } + }).filter(Objects::nonNull).findFirst().get(); + } + + public static String mapRDAIsoToLanguageIso(Language lang) { + return langMap.get(lang.value()).toString(); + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/LicenseRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/LicenseRDAMapper.java new file mode 100644 index 0000000..fef1ff6 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/LicenseRDAMapper.java @@ -0,0 +1,135 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.License; +import eu.eudat.file.transformer.utils.json.JsonSearcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +public class LicenseRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(LicenseRDAMapper.class); + + public static License toRDA(List nodes) { + License rda = new License(); + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dataset.distribution.license")).findFirst().orElse(""); + String value = node.getData().getValue(); + if(value == null || value.isEmpty()){ + continue; + } + for (LicenceProperties licenceProperties: LicenceProperties.values()) { + if (rdaProperty.contains(licenceProperties.getName())) { + switch (licenceProperties) { + case LICENSE_REF: + try { + rda.setLicenseRef(URI.create(value)); + } catch (IllegalArgumentException e) { + logger.warn(e.getLocalizedMessage() + ". Skipping url parsing"); + } + break; + case START_DATE: + rda.setStartDate(value); + break; + } + } + } + + /*if (rdaProperty.contains("license_ref")) { + rda.setLicenseRef(URI.create(value)); + rda.setAdditionalProperty("license_refId", node.get("id").asText()); + } else if (rdaProperty.contains("start_date")) { + rda.setStartDate(value); + rda.setAdditionalProperty("start_dateId", node.get("id").asText()); + }*/ + } + + if(rda.getLicenseRef() == null || rda.getStartDate() == null){ + return null; + } + + return rda; + } + + //TODO + /*public static List toProperties(List rdas) { + List properties = new ArrayList<>(); + + rdas.forEach(rda -> { + + rda.getAdditionalProperties().entrySet().forEach(entry -> { + Field field = new Field(); + field.setKey(entry.getValue().toString()); + switch (entry.getKey()) { + case "license_refId": + field.setValue(rda.getLicenseRef().toString()); + break; + case "start_dateId": + field.setValue(rda.getStartDate()); + break; + } + properties.add(field); + + }); + }); + + return properties; + } + + public static List toProperties(License rda, JsonNode root) { + List properties = new ArrayList<>(); + + List licenseNodes = JsonSearcher.findNodes(root, "schematics", "rda.dataset.distribution.license"); + + for (JsonNode licenseNode: licenseNodes) { + for (LicenceProperties licenceProperty: LicenceProperties.values()) { + JsonNode schematics = licenseNode.get("schematics"); + if(schematics.isArray()) { + for (JsonNode schematic : schematics) { + if (schematic.asText().endsWith(licenceProperty.getName())) { + switch (licenceProperty) { + case LICENSE_REF: + if (rda.getLicenseRef() != null) { + Field field = new Field(); + field.setKey(licenseNode.get("id").asText()); + field.setValue(rda.getLicenseRef().toString()); + properties.add(field); + } + break; + case START_DATE: + Field field = new Field(); + field.setKey(licenseNode.get("id").asText()); + field.setValue(rda.getStartDate()); + properties.add(field); + break; + } + } + break; + } + } + } + } + + return properties; + }*/ + + public enum LicenceProperties { + LICENSE_REF("license_ref"), + START_DATE("start_date"); + + private String name; + + LicenceProperties(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataRDAMapper.java new file mode 100644 index 0000000..8d6a75a --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataRDAMapper.java @@ -0,0 +1,230 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.TextNode; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.Metadatum; + +import eu.eudat.file.transformer.utils.string.MyStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +public class MetadataRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(MetadataRDAMapper.class); + + public static List toRDAList(List nodes) { + ObjectMapper mapper = new ObjectMapper(); + Map rdaMap = new HashMap<>(); + List rdas = new ArrayList<>(); + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dataset.metadata")).findFirst().orElse(""); + try { + if (node.getData() == null) { + continue; + } + String stringValue = node.getData().getValue().startsWith("[") ? node.getData().getValue() : "\"" + node.getData().getValue() + "\""; + JsonNode rdaValue = mapper.readTree(stringValue); + + for (PropertyName propertyName : PropertyName.values()) { + if (rdaProperty.contains(propertyName.getName())) { + switch (propertyName) { + case METADATA_STANDARD_ID: + if (rdaValue instanceof ArrayNode) { + for (Iterator it = rdaValue.elements(); it.hasNext(); ) { + JsonNode data = null; + data = mapper.readTree(it.next().asText()); + if (data.get("uri") != null) { + rdas.add(new Metadatum()); + rdas.get(rdas.size() - 1).setMetadataStandardId(MetadataStandardIdRDAMapper.toRDA(data.get("uri").asText())); + rdas.get(rdas.size() - 1).setDescription(data.get("label").asText()); + rdas.get(rdas.size() - 1).setAdditionalProperty("fieldId", node.getId()); + rdas.get(rdas.size() - 1).setAdditionalProperty("valueId", data.get("id").asText()); + rdaMap.put(data.get("uri").asText(), node.getNumbering()); + } + } + } else if (rdaValue instanceof TextNode && rdaProperty.contains("identifier") && !rdaValue.asText().isEmpty()) { + rdas.add(new Metadatum()); + rdas.get(rdas.size() - 1).setMetadataStandardId(MetadataStandardIdRDAMapper.toRDA(rdaValue.asText())); + rdas.get(rdas.size() - 1).setAdditionalProperty("identifierId", node.getId()); + rdaMap.put(rdaValue.asText(), node.getNumbering()); + } + break; + case DESCRIPTION: + if (!rdaValue.asText().isEmpty()) { + Metadatum rda = getRelative(rdas, rdaMap, node.getNumbering()); + if (rda != null) { + rda.setDescription(rdaValue.asText()); + rda.setAdditionalProperty("descriptionId", node.getId()); + } else { + rdas.stream().filter(rda1 -> rda1.getDescription() == null || rda1.getDescription().isEmpty()).forEach(rda1 -> rda1.setDescription(rdaValue.asText())); + } + } + break; + case LANGUAGE: + String language = rdaValue.asText(); + Metadatum.Language lang = Metadatum.Language.fromValue(language); + Metadatum rda = getRelative(rdas, rdaMap, node.getNumbering()); + if (rda != null) { + rda.setLanguage(lang); + rda.setAdditionalProperty("languageId", node.getId()); + } else { + rdas.forEach(rda1 -> rda1.setLanguage(lang)); + } + break; + } + } + } + } catch (JsonProcessingException e) { + logger.error(e.getMessage(), e); + } + + } + + return rdas; + } + + //TODO +/* + public static void toProperties(List rdas, List fields) { + List standardIds = new ArrayList<>(); + ObjectMapper mapper = new ObjectMapper(); + rdas.forEach(rda -> { + rda.getAdditionalProperties().entrySet().forEach(entry -> { + try { + switch (entry.getKey()) { + case "fieldId": + Map metadata = toMap(rda); + standardIds.add(metadata); + Field field1 = new Field(); + field1.setKey(entry.getValue().toString()); + field1.setValue(mapper.writeValueAsString(standardIds)); + properties.add(field1); + break; + case "identifierId": + Field field2 = new Field(); + field2.setKey(entry.getValue().toString()); + field2.setValue(rda.getMetadataStandardId().getIdentifier()); + properties.add(field2); + break; + case "descriptionId": + Field field3 = new Field(); + field3.setKey(entry.getValue().toString()); + field3.setValue(rda.getDescription()); + properties.add(field3); + break; + case "languageId": + if (rda.getLanguage() != null) { + Field field4 = new Field(); + field4.setKey(entry.getValue().toString()); + field4.setValue(rda.getLanguage().value()); + properties.add(field4); + } + break; + } + }catch (Exception e) { + logger.error(e.getMessage(), e); + } + }); + }); + + return properties; + } +*/ + + public static Metadatum toRDA(JsonNode node) { + Metadatum rda = new Metadatum(); + String rdaProperty = ""; + JsonNode schematics = node.get("schematics"); + if(schematics.isArray()){ + for(JsonNode schematic: schematics){ + if(schematic.asText().startsWith("rda.dataset.metadata")){ + rdaProperty = schematic.asText(); + break; + } + } + } + JsonNode rdaValue = node.get("value"); + if (rdaProperty.contains("metadata_standard_id")) { + if (rdaValue instanceof ArrayNode) { + for (Iterator it = rdaValue.elements(); it.hasNext(); ) { + JsonNode data = it.next(); + if (data.get("uri") != null) { + rda.setMetadataStandardId(MetadataStandardIdRDAMapper.toRDA(data.get("uri").asText())); + } + } + } + } else if (rdaProperty.contains("description")) { + rda.setDescription(rdaValue.asText()); + } else if (rdaProperty.contains("language")) { + String language = rdaValue.asText(); + Metadatum.Language lang = Metadatum.Language.fromValue(language); + rda.setLanguage(lang); + } + + return rda; + } + + private static Metadatum getRelative(List rdas, Map rdaMap, String numbering) { + String target = rdaMap.entrySet().stream().filter(entry -> MyStringUtils.getFirstDifference(entry.getValue(), numbering) > 0) + .max(Comparator.comparingInt(entry -> MyStringUtils.getFirstDifference(entry.getValue(), numbering))).map(Map.Entry::getKey).orElse(""); + return rdas.stream().filter(rda -> rda.getMetadataStandardId().getIdentifier().equals(target)).distinct().findFirst().orElse(null); + } + + private enum PropertyName { + METADATA_STANDARD_ID("metadata_standard_id"), + DESCRIPTION("description"), + LANGUAGE("language"); + + private final String name; + + PropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + private static Map toMap(Metadatum rda) { + Map result = new HashMap<>(); + + ObjectMapper mapper = new ObjectMapper(); + + Map metadata = mapper.convertValue(rda, Map.class); + + Map additionalProperties = mapper.convertValue(metadata.get("additional_properties"), Map.class); + + String id = additionalProperties.remove("valueId"); + additionalProperties.clear(); + additionalProperties.put("id", id); + + Map metadataStandardId = mapper.convertValue(metadata.get("metadata_standard_id"), Map.class); + + String url = metadataStandardId.remove("identifier"); + metadataStandardId.remove("type"); + metadataStandardId.put("uri", url); + + metadata.remove("additional_properties"); + metadata.remove("metadata_standard_id"); + + Map newMetadata = metadata.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().toString())); + + String label = newMetadata.remove("description"); + newMetadata.put("label", label); + + result.putAll(newMetadata); + result.putAll(metadataStandardId); + result.putAll(additionalProperties); + + return result; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataStandardIdRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataStandardIdRDAMapper.java new file mode 100644 index 0000000..5f5005d --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/MetadataStandardIdRDAMapper.java @@ -0,0 +1,13 @@ +package eu.eudat.file.transformer.rda.mapper; + +import eu.eudat.file.transformer.rda.MetadataStandardId; + +public class MetadataStandardIdRDAMapper { + + public static MetadataStandardId toRDA(String uri) { + MetadataStandardId rda = new MetadataStandardId(); + rda.setIdentifier(uri); + rda.setType(MetadataStandardId.Type.URL); + return rda; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ProjectRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ProjectRDAMapper.java new file mode 100644 index 0000000..c614b4d --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/ProjectRDAMapper.java @@ -0,0 +1,69 @@ +package eu.eudat.file.transformer.rda.mapper; +import eu.eudat.file.transformer.enums.ReferenceType; +import eu.eudat.file.transformer.models.reference.DefinitionFileTransformerModel; +import eu.eudat.file.transformer.models.reference.FieldFileTransformerModel; +import eu.eudat.file.transformer.models.reference.ReferenceFileTransformerModel; +import eu.eudat.file.transformer.rda.Project; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class ProjectRDAMapper { + private final static Logger logger = LoggerFactory.getLogger(ProjectRDAMapper.class); + + public static Project toRDA(ReferenceFileTransformerModel project, ReferenceFileTransformerModel grant, ReferenceFileTransformerModel funder) { + Project rda = new Project(); + try { + rda.setTitle(project.getLabel()); + rda.setDescription(project.getDescription()); + String startDateString = project.getDefinition().getFields().stream().filter(field -> field.getCode().equals("startDate")).map(FieldFileTransformerModel::getValue).findFirst().orElse(null); + if (startDateString != null) { + rda.setStart(startDateString); + } + String endDateString = project.getDefinition().getFields().stream().filter(field -> field.getCode().equals("endDate")).map(FieldFileTransformerModel::getValue).findFirst().orElse(null); + if (endDateString != null) { + rda.setEnd(endDateString); + } + rda.setFunding(List.of(FundingRDAMapper.toRDA(grant, funder))); + + if (rda.getTitle() == null) { + throw new IllegalArgumentException("Project Title is missing"); + } + } catch (Exception e) { + logger.error(e.getLocalizedMessage(), e); + } + + return rda; + } + + public static List toEntity(Project rda) { + List entities = new ArrayList<>(); + ReferenceFileTransformerModel project = new ReferenceFileTransformerModel(); + project.setLabel(rda.getTitle()); + project.setDescription(rda.getDescription()); + project.setType(ReferenceType.Project); + DefinitionFileTransformerModel projectDefinition = new DefinitionFileTransformerModel(); + projectDefinition.setFields(new ArrayList<>()); + if (rda.getStart() != null && !rda.getStart().isEmpty()) { + FieldFileTransformerModel startDateField = new FieldFileTransformerModel(); + startDateField.setCode("startDate"); + startDateField.setValue(rda.getStart()); + projectDefinition.getFields().add(startDateField); + } + if (rda.getEnd() != null && !rda.getEnd().isEmpty()) { + FieldFileTransformerModel startDateField = new FieldFileTransformerModel(); + startDateField.setCode("endDate"); + startDateField.setValue(rda.getEnd()); + projectDefinition.getFields().add(startDateField); + } + project.setDefinition(projectDefinition); + entities.add(project); + + for (int i = 0; i < rda.getFunding().size(); i++) { + entities.addAll(FundingRDAMapper.toEntity(rda.getFunding().get(i))); + } + + return entities; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/SecurityAndPrivacyRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/SecurityAndPrivacyRDAMapper.java new file mode 100644 index 0000000..f91e220 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/SecurityAndPrivacyRDAMapper.java @@ -0,0 +1,152 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.SecurityAndPrivacy; +import eu.eudat.file.transformer.utils.string.MyStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.stream.Collectors; + +public class SecurityAndPrivacyRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(SecurityAndPrivacyRDAMapper.class); + + public static List toRDAList(List nodes) { + Map rdaMap = new HashMap<>(); + + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dataset.security_and_privacy")).findFirst().orElse(""); + if (node.getData() == null) { + continue; + } + String rdaValue = node.getData().getValue(); + if(rdaValue == null || rdaValue.isEmpty()){ + continue; + } + SecurityAndPrivacy rda = getRelative(rdaMap, node.getNumbering()); + if (!rdaMap.containsValue(rda)) { + rdaMap.put(node.getNumbering(), rda); + } + for (ExportPropertyName exportPropertyName : ExportPropertyName.values()) { + if (rdaProperty.contains(exportPropertyName.getName())) { + switch (exportPropertyName) { + case TITLE: + rda.setTitle(rdaValue); + rda.getAdditionalProperties().put(ImportPropertyName.TITLE.getName(), node.getId()); + break; + case DESCRIPTION: + rda.setDescription(rdaValue); + rda.getAdditionalProperties().put(ImportPropertyName.DESCRIPTION.getName(), node.getId()); + break; + } + } + } + } + + return rdaMap.values().stream() + .filter(sap -> sap.getTitle() != null) + .collect(Collectors.toList()); + } + + //TODO +/* + public static List toProperties(List rdas) { + List properties = new ArrayList<>(); + rdas.forEach(rda -> rda.getAdditionalProperties().entrySet().forEach(entry -> { + try { + Field field = new Field(); + field.setKey(entry.getValue().toString()); + ImportPropertyName importPropertyName = ImportPropertyName.fromString(entry.getKey()); + switch(importPropertyName) { + case TITLE: + field.setValue(rda.getTitle()); + break; + case DESCRIPTION: + field.setValue(rda.getDescription()); + break; + } + properties.add(field); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + })); + + return properties; + } +*/ + + public static SecurityAndPrivacy toRDA(JsonNode node) { + SecurityAndPrivacy rda = new SecurityAndPrivacy(); + String rdaProperty = ""; + JsonNode schematics = node.get("schematics"); + if(schematics.isArray()){ + for(JsonNode schematic: schematics){ + if(schematic.asText().startsWith("rda.dataset.security_and_privacy")){ + rdaProperty = schematic.asText(); + break; + } + } + } + String value = node.get("value").asText(); + + if (rdaProperty.contains("description")) { + rda.setDescription(value); + } + if (rdaProperty.contains("title")) { + rda.setTitle(value); + } + + if (rda.getTitle() == null) { + throw new IllegalArgumentException("Security And Privacy Title is missing"); + } + + return rda; + } + + private static SecurityAndPrivacy getRelative(Map rdaMap, String numbering) { + return rdaMap.entrySet().stream().filter(entry -> MyStringUtils.getFirstDifference(entry.getKey(), numbering) > 0) + .max(Comparator.comparingInt(entry -> MyStringUtils.getFirstDifference(entry.getKey(), numbering))).map(Map.Entry::getValue).orElse(new SecurityAndPrivacy()); + } + + private enum ExportPropertyName { + TITLE("title"), + DESCRIPTION("description"); + + private String name; + + ExportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + private enum ImportPropertyName { + TITLE("titleId"), + DESCRIPTION("descriptionId"); + + private String name; + + ImportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public static ImportPropertyName fromString(String name) throws Exception { + for (ImportPropertyName importPropertyName: ImportPropertyName.values()) { + if (importPropertyName.getName().equals(name)) { + return importPropertyName; + } + } + throw new Exception("Property not available"); + } + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/rda/mapper/TechnicalResourceRDAMapper.java b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/TechnicalResourceRDAMapper.java new file mode 100644 index 0000000..6154faf --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/rda/mapper/TechnicalResourceRDAMapper.java @@ -0,0 +1,153 @@ +package eu.eudat.file.transformer.rda.mapper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.rda.TechnicalResource; +import eu.eudat.file.transformer.utils.string.MyStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.stream.Collectors; + +public class TechnicalResourceRDAMapper { + private static final Logger logger = LoggerFactory.getLogger(TechnicalResourceRDAMapper.class); + + public static List toRDAList(List nodes) { + Map rdaMap = new HashMap<>(); + + for (FieldFileTransformerModel node: nodes) { + String rdaProperty = node.getSchematics().stream().filter(schematic -> schematic.startsWith("rda.dataset.technical_resource")).findFirst().orElse(""); + if (node.getData() == null) { + continue; + } + String rdaValue = node.getData().getValue(); + if(rdaValue == null || rdaValue.isEmpty()){ + continue; + } + TechnicalResource rda = getRelative(rdaMap, node.getNumbering()); + if (!rdaMap.containsValue(rda)) { + rdaMap.put(node.getNumbering(), rda); + } + for (ExportPropertyName exportPropertyName : ExportPropertyName.values()) { + if (rdaProperty.contains(exportPropertyName.getName())) { + switch (exportPropertyName) { + case NAME: + rda.setName(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.NAME.getName(), node.getId()); + break; + case DESCRIPTION: + rda.setDescription(rdaValue); + rda.setAdditionalProperty(ImportPropertyName.DESCRIPTION.getName(), node.getId()); + break; + } + } + } + } + + return rdaMap.values().stream() + .filter(tr -> tr.getName() != null) + .collect(Collectors.toList()); + } + + //TODO +/* + public static List toProperties(List rdas) { + List properties = new ArrayList<>(); + + rdas.forEach(rda -> rda.getAdditionalProperties().entrySet().forEach(entry -> { + try { + Field field = new Field(); + field.setKey(entry.getValue().toString()); + ImportPropertyName importPropertyName = ImportPropertyName.fromString(entry.getKey()); + switch(importPropertyName) { + case DESCRIPTION: + field.setValue(rda.getDescription()); + break; + case NAME: + field.setValue(rda.getName()); + break; + } + properties.add(field); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + })); + + return properties; + } +*/ + + public static TechnicalResource toRDA(JsonNode node) { + TechnicalResource rda = new TechnicalResource(); + String rdaProperty = ""; + JsonNode schematics = node.get("schematics"); + if(schematics.isArray()){ + for(JsonNode schematic: schematics){ + if(schematic.asText().startsWith("rda.dataset.technical_resource")){ + rdaProperty = schematic.asText(); + break; + } + } + } + String value = node.get("value").asText(); + + if (rdaProperty.contains("description")) { + rda.setDescription(value); + } + if (rdaProperty.contains("name")) { + rda.setName(value); + } + + if (rda.getName() == null) { + throw new IllegalArgumentException("Technical Resources Name is missing"); + } + + return rda; + } + + private static TechnicalResource getRelative(Map rdaMap, String numbering) { + return rdaMap.entrySet().stream().filter(entry -> MyStringUtils.getFirstDifference(entry.getKey(), numbering) > 0) + .max(Comparator.comparingInt(entry -> MyStringUtils.getFirstDifference(entry.getKey(), numbering))).map(Map.Entry::getValue).orElse(new TechnicalResource()); + } + + private enum ExportPropertyName { + NAME("name"), + DESCRIPTION("description"); + + private String name; + + ExportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + private enum ImportPropertyName { + NAME("nameId"), + DESCRIPTION("descriptionId"); + + private String name; + + ImportPropertyName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public static ImportPropertyName fromString(String name) throws Exception { + for (ImportPropertyName importPropertyName: ImportPropertyName.values()) { + if (importPropertyName.getName().equals(name)) { + return importPropertyName; + } + } + throw new Exception("Property name not available"); + } + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/utils/descriptionTemplate/TemplateFieldSearcher.java b/core/src/main/java/eu/eudat/file/transformer/utils/descriptionTemplate/TemplateFieldSearcher.java new file mode 100644 index 0000000..d1d31fb --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/utils/descriptionTemplate/TemplateFieldSearcher.java @@ -0,0 +1,63 @@ +package eu.eudat.file.transformer.utils.descriptionTemplate; + +import eu.eudat.file.transformer.models.descriptiontemplate.DescriptionTemplateFileTransformerModel; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldFileTransformerModel; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.FieldSetFileTransformerModel; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.PageFileTransformerModel; +import eu.eudat.file.transformer.models.descriptiontemplate.definition.SectionFileTransformerModel; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +public class TemplateFieldSearcher { + + public static List searchFields(DescriptionTemplateFileTransformerModel template, String key, String value) { + List result; + List pages = template.getDefinition().getPages(); + result = pages.stream().flatMap(pageFileTransformerModel -> searchFieldsFromSections(pageFileTransformerModel.getSections(), key, value).stream()).toList(); + return result; + } + + private static List searchFieldsFromSections(List sections, String key, String value) { + List result = new ArrayList<>(); + for (SectionFileTransformerModel section : sections) { + if (section.getSections() != null && !section.getSections().isEmpty()) { + result.addAll(searchFieldsFromSections(section.getSections(), key, value)); + } + if (section.getFieldSets() != null && !section.getFieldSets().isEmpty()) { + List fieldSets = section.getFieldSets(); + for (FieldSetFileTransformerModel fieldSet : fieldSets) { + List fields = fieldSet.getFields(); + for (FieldFileTransformerModel field : fields) { + Method keyGetter = Arrays.stream(FieldFileTransformerModel.class.getDeclaredMethods()).filter(method -> method.getName().equals(makeGetter(key))).findFirst().orElse(null); + if (keyGetter != null && keyGetter.canAccess(field)) { + try { + if (keyGetter.invoke(field).equals(value) || keyGetter.invoke(field).toString().startsWith(value)) { + result.add(field); + } else if(keyGetter.getReturnType().isAssignableFrom(List.class)) { + List nodes = (List) keyGetter.invoke(field); + for (Object item : nodes) { + if (item.toString().equals(value) || item.toString().startsWith(value)) { + result.add(field); + } + } + } + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + } + } + } + } + return result; + } + + private static String makeGetter(String fieldName) { + return "get" + fieldName.substring(0, 1).toUpperCase(Locale.ROOT) + fieldName.substring(1); + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/utils/json/JsonSearcher.java b/core/src/main/java/eu/eudat/file/transformer/utils/json/JsonSearcher.java new file mode 100644 index 0000000..a5e33e6 --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/utils/json/JsonSearcher.java @@ -0,0 +1,81 @@ +package eu.eudat.file.transformer.utils.json; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +public class JsonSearcher { + + public static List findNodes(JsonNode root, String key, String value) { + return findNodes(root, key, value, false); + } + + public static List findNodes(JsonNode root, String key, String value, boolean parent) { + List nodes = new ArrayList<>(); + for (Iterator it = root.elements(); it.hasNext(); ) { + JsonNode node = it.next(); + int found = 0; + for (Iterator iter = node.fieldNames(); iter.hasNext(); ) { + String fieldName = iter.next(); + if (fieldName.equals(key)) { + if (node.get(fieldName).asText().equals(value) || node.get(fieldName).asText().startsWith(value)) { + if (parent) { + nodes.add(root); + } else { + nodes.add(node); + } + found++; + } + else if(node.get(fieldName).isArray()){ + for(JsonNode item: node.get(fieldName)){ + if(item.asText().equals(value) || item.asText().startsWith(value)){ + if (parent) { + nodes.add(root); + } else { + nodes.add(node); + } + found++; + } + } + } + } + + } + if (found == 0) { + nodes.addAll(findNodes(node, key, value, parent)); + } + } + return nodes; + } + + public static List getParentValues(JsonNode root, String childValue, String key) { + List values = new LinkedList<>(); + + for (Iterator it = root.elements(); it.hasNext(); ) { + JsonNode node = it.next(); + int found = 0; + for (Iterator iter = node.fieldNames(); iter.hasNext(); ) { + String fieldName = iter.next(); + if (fieldName.equals(key)) { + if (node.get(fieldName).asText().equals(childValue) || node.get(fieldName).asText().startsWith(childValue)) { + values.add(childValue); + found++; + } + } + + } + if (found == 0) { + values.addAll(getParentValues(node, childValue, key)); + if (!values.isEmpty() && node.has(key)) { + values.add(node.get(key).asText()); + values.remove(childValue); + } + } + } + + return values; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/utils/service/storage/FileStorageService.java b/core/src/main/java/eu/eudat/file/transformer/utils/service/storage/FileStorageService.java new file mode 100644 index 0000000..80493ec --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/utils/service/storage/FileStorageService.java @@ -0,0 +1,44 @@ +package eu.eudat.file.transformer.utils.service.storage; + +import eu.eudat.file.transformer.configuration.FileStorageProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.nio.file.*; +import java.util.UUID; + +@Service +public class FileStorageService { + private final static Logger logger = LoggerFactory.getLogger(FileStorageService.class); + + private final FileStorageProperties properties; + + @Autowired + public FileStorageService(FileStorageProperties properties) { + this.properties = properties; + } + + public String storeFile(byte[] data) { + try { + String fileName = UUID.randomUUID().toString(); + Path storagePath = Paths.get(properties.getTransientPath() + "/" + fileName); + Files.write(storagePath, data, StandardOpenOption.CREATE_NEW); + return fileName; + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + return null; + } + + public byte[] readFile(String fileRef) { + try (FileInputStream inputStream = new FileInputStream(properties.getTransientPath() + "/" + fileRef)) { + return inputStream.readAllBytes(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + return new byte[1]; + } +} diff --git a/core/src/main/java/eu/eudat/file/transformer/utils/string/MyStringUtils.java b/core/src/main/java/eu/eudat/file/transformer/utils/string/MyStringUtils.java new file mode 100644 index 0000000..7a5055e --- /dev/null +++ b/core/src/main/java/eu/eudat/file/transformer/utils/string/MyStringUtils.java @@ -0,0 +1,21 @@ +package eu.eudat.file.transformer.utils.string; + +public class MyStringUtils { + + public static int getFirstDifference(String s1, String s2) { + char[] s1ar = s1.toCharArray(); + char[] s2ar = s2.toCharArray(); + + for(int i = 0; i < s1ar.length; i++) { + if (s2ar.length > i) { + if (s1ar[i] != s2ar[i]) { + return i; + } + } else { + return i; + } + } + + return -1; + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8b5b8f2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.1.0 + + + + gr.cite.opendmp + file-transformer-rda-parent + ${revision} + pom + + + 21 + 21 + 21 + 1.0.0-SNAPSHOT + + + + + org.yaml + snakeyaml + 2.0 + + + + + core + web + + + diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..7614d63 --- /dev/null +++ b/settings.xml @@ -0,0 +1,29 @@ + + + + ossrh + ${server_username} + ${server_password} + + + dev + ${server_username} + ${server_password} + + + + + dev + + true + + + + dev + Dev Profile + ${devProfileUrl} + + + + + \ No newline at end of file diff --git a/web/pom.xml b/web/pom.xml new file mode 100644 index 0000000..e613974 --- /dev/null +++ b/web/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + gr.cite.opendmp + file-transformer-rda-parent + ${revision} + ../pom.xml + + + file-transformer-rda-web + ${revision} + jar + + + 21 + 21 + 21 + 1.0.0-SNAPSHOT + + + + + gr.cite.opendmp + file-transformer-rda + ${revision} + + + org.springframework.boot + spring-boot-starter-web + + + gr.cite + oidc-authn + 2.1.0 + + + gr.cite + cache + 2.1.0 + + + org.springframework.boot + spring-boot-starter-cache + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 3.1.0 + + + + + diff --git a/web/src/main/java/eu/eudat/file/transformer/FileTransformerApplication.java b/web/src/main/java/eu/eudat/file/transformer/FileTransformerApplication.java new file mode 100644 index 0000000..b08edb9 --- /dev/null +++ b/web/src/main/java/eu/eudat/file/transformer/FileTransformerApplication.java @@ -0,0 +1,16 @@ +package eu.eudat.file.transformer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackages = { + "eu.eudat.file.transformer.*", + "gr.cite.tools", + "gr.cite.commons" +}) +public class FileTransformerApplication { + + public static void main(String[] args) { + SpringApplication.run(FileTransformerApplication.class, args); + } +} diff --git a/web/src/main/java/eu/eudat/file/transformer/config/SecurityConfiguration.java b/web/src/main/java/eu/eudat/file/transformer/config/SecurityConfiguration.java new file mode 100644 index 0000000..d0269e8 --- /dev/null +++ b/web/src/main/java/eu/eudat/file/transformer/config/SecurityConfiguration.java @@ -0,0 +1,76 @@ +package eu.eudat.file.transformer.config; + +import gr.cite.commons.web.oidc.configuration.WebSecurityProperties; +import gr.cite.commons.web.oidc.configuration.filter.ApiKeyFilter; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManagerResolver; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; + +import java.util.Set; + +@Configuration +@EnableWebSecurity +public class SecurityConfiguration { + + private final ApiKeyFilter apiKeyFilter; + private final WebSecurityProperties webSecurityProperties; + private final AuthenticationManagerResolver authenticationManagerResolver; + + @Autowired + public SecurityConfiguration(ApiKeyFilter apiKeyFilter, WebSecurityProperties webSecurityProperties, AuthenticationManagerResolver authenticationManagerResolver) { + this.apiKeyFilter = apiKeyFilter; + this.webSecurityProperties = webSecurityProperties; + this.authenticationManagerResolver = authenticationManagerResolver; + } + + @Bean + protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + if (webSecurityProperties.isEnabled()) { + http.csrf(AbstractHttpConfigurer::disable) + .cors(Customizer.withDefaults()) + .addFilterBefore(apiKeyFilter, AbstractPreAuthenticatedProcessingFilter.class) + .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry + .requestMatchers(buildAntPatterns(webSecurityProperties.getAuthorizedEndpoints())).authenticated() + .requestMatchers(buildAntPatterns(webSecurityProperties.getAllowedEndpoints())).anonymous()) + .sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.NEVER)) + .oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver)); + return http.build(); + } else { + return http.csrf(AbstractHttpConfigurer::disable) + .cors(Customizer.withDefaults()) + .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> + authorizationManagerRequestMatcherRegistry.anyRequest().anonymous()) + .build(); + } + } + + private String[] buildAntPatterns(Set endpoints) { + if (endpoints == null) { + return new String[0]; + } + return endpoints.stream() + .filter(endpoint -> endpoint != null && !endpoint.isBlank()) + .map(endpoint -> "/" + stripUnnecessaryCharacters(endpoint) + "/**") + .toArray(String[]::new); + } + + private String stripUnnecessaryCharacters(String endpoint) { + endpoint = endpoint.strip(); + if (endpoint.startsWith("/")) { + endpoint = endpoint.substring(1); + } + if (endpoint.endsWith("/")) { + endpoint = endpoint.substring(0, endpoint.length() - 1); + } + return endpoint; + } +} diff --git a/web/src/main/java/eu/eudat/file/transformer/controller/FileTransformerController.java b/web/src/main/java/eu/eudat/file/transformer/controller/FileTransformerController.java new file mode 100644 index 0000000..76b384b --- /dev/null +++ b/web/src/main/java/eu/eudat/file/transformer/controller/FileTransformerController.java @@ -0,0 +1,48 @@ +package eu.eudat.file.transformer.controller; + +import eu.eudat.file.transformer.interfaces.FileTransformerClient; +import eu.eudat.file.transformer.interfaces.FileTransformerConfiguration; +import eu.eudat.file.transformer.models.description.DescriptionFileTransformerModel; +import eu.eudat.file.transformer.models.dmp.DmpFileTransformerModel; +import eu.eudat.file.transformer.models.misc.FileEnvelope; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/file") +public class FileTransformerController { + + private final FileTransformerClient fileTransformerExecutor; + + @Autowired + public FileTransformerController(FileTransformerClient fileTransformerExecutor) { + this.fileTransformerExecutor = fileTransformerExecutor; + } + + @PostMapping("/export/dmp") + public FileEnvelope exportDmp(@RequestBody DmpFileTransformerModel dmpDepositModel) throws Exception { + return fileTransformerExecutor.exportDmp(dmpDepositModel); + } + + @PostMapping("/export/description") + public FileEnvelope exportDescription(@RequestBody DescriptionFileTransformerModel descriptionFileTransformerModel, @RequestParam(value = "format",required = false)String format, @RequestParam(value = "descriptionId",required = false) String descriptionId) throws Exception { + return fileTransformerExecutor.exportDescription(descriptionFileTransformerModel, format); + } + + @PostMapping("/import/dmp") + public DmpFileTransformerModel importFileToDmp(@RequestBody FileEnvelope fileEnvelope) { + return fileTransformerExecutor.importDmp(fileEnvelope); + } + + @PostMapping("/import/description") + public DescriptionFileTransformerModel importFileToDescription(@RequestBody FileEnvelope fileEnvelope) { + return fileTransformerExecutor.importDescription(fileEnvelope); + } + + @GetMapping("/formats") + public FileTransformerConfiguration getSupportedFormats() { + return fileTransformerExecutor.getConfiguration(); + } +} diff --git a/web/src/main/resources/config/application.yml b/web/src/main/resources/config/application.yml new file mode 100644 index 0000000..9bb90cb --- /dev/null +++ b/web/src/main/resources/config/application.yml @@ -0,0 +1,11 @@ +spring: + jackson: + default-property-inclusion: non_null + config: + import: optional:classpath:config/app.env[.properties], optional:file:../config/app.env[.properties], + optional:classpath:config/server.yml[.yml], optional:classpath:config/server-${spring.profiles.active}.yml[.yml], optional:file:../config/server-${spring.profiles.active}.yml[.yml], + optional:classpath:config/storage.yml[.yml], optional:classpath:config/storage-${spring.profiles.active}.yml[.yml], optional:file:../config/storage-${spring.profiles.active}.yml[.yml], + optional:classpath:config/security.yml[.yml], optional:classpath:config/security-${spring.profiles.active}.yml[.yml], optional:file:../config/security-${spring.profiles.active}.yml[.yml], + optional:classpath:config/cache.yml[.yml], optional:classpath:config/cache-${spring.profiles.active}.yml[.yml], optional:file:../config/cache-${spring.profiles.active}.yml[.yml], + optional:classpath:config/pdf.yml[.yml], optional:classpath:config/pdf-${spring.profiles.active}.yml[.yml], optional:file:../config/pdf-${spring.profiles.active}.yml[.yml] + diff --git a/web/src/main/resources/config/cache.yml b/web/src/main/resources/config/cache.yml new file mode 100644 index 0000000..005e6de --- /dev/null +++ b/web/src/main/resources/config/cache.yml @@ -0,0 +1,16 @@ +cache: + manager: + fallbackToNoOpCache: true + caffeineCaches: + - names: [ "apikey" ] + allowNullValues: true + initialCapacity: 100 + maximumSize: 500 + enableRecordStats: false + expireAfterWriteMinutes: 10 + expireAfterAccessMinutes: 10 + refreshAfterWriteMinutes: 10 + mapCaches: + apiKey: + name: apikey + keyPattern: resolve_$keyhash$:v0 \ No newline at end of file diff --git a/web/src/main/resources/config/pdf.yml b/web/src/main/resources/config/pdf.yml new file mode 100644 index 0000000..64f4ae7 --- /dev/null +++ b/web/src/main/resources/config/pdf.yml @@ -0,0 +1,3 @@ +pdf: + converter: + url: ${PDF_CONVERTER_URL:} \ No newline at end of file diff --git a/web/src/main/resources/config/security.yml b/web/src/main/resources/config/security.yml new file mode 100644 index 0000000..ad38bd8 --- /dev/null +++ b/web/src/main/resources/config/security.yml @@ -0,0 +1,20 @@ +web: + security: + enabled: true + authorized-endpoints: [ api ] + allowed-endpoints: [ health ] + idp: + api-key: + enabled: true + authorization-header: Authorization + client-id: ${IDP_APIKEY_CLIENT_ID:} + client-secret: ${IDP_APIKEY_CLIENT_SECRET:} + scope: ${IDP_APIKEY_SCOPE:} + resource: + token-type: JWT #| opaque + opaque: + client-id: ${IDP_OPAQUE_CLIENT_ID:} + client-secret: ${IDP_OPAQUE_CLIENT_SECRET:} + jwt: + claims: [ role, x-role ] + issuer-uri: ${IDP_ISSUER_URI:} \ No newline at end of file diff --git a/web/src/main/resources/config/server.yml b/web/src/main/resources/config/server.yml new file mode 100644 index 0000000..755337e --- /dev/null +++ b/web/src/main/resources/config/server.yml @@ -0,0 +1,12 @@ +server: + port: 8086 + tomcat: + threads: + max: 20 + max-connections: 10000 + +spring: + servlet: + multipart: + max-file-size: 10MB + max-request-size: 10MB \ No newline at end of file diff --git a/web/src/main/resources/config/storage.yml b/web/src/main/resources/config/storage.yml new file mode 100644 index 0000000..c6b4d30 --- /dev/null +++ b/web/src/main/resources/config/storage.yml @@ -0,0 +1,4 @@ +file: + storage: + temp: ${TEMP_PATH} + transient-path: ${TRANSIENT_PATH} \ No newline at end of file diff --git a/web/src/main/resources/documents/h2020.docx b/web/src/main/resources/documents/h2020.docx new file mode 100644 index 0000000000000000000000000000000000000000..b0e721ab0234053b1488fd2d6b2b8af8a066d1c2 GIT binary patch literal 30266 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⋘GtWx7yn2#=O-m5*C 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 AsHFdC@ml^`Eug$wO|*OI~H)i|r3LwTnjdUxIC zyC(z$PGkBi#1qd%ea^HI=IS=q1(*x8cv7kJ7E>|UhSaM)mlB~o-elbfguDN1uE)&3 zfcFNK9D(v34P>MSa!>pDPKeRK(&lHXgI2!yuX`G(k#$uV_~D+`NPdD6d6b{*a~hyP zPP`i^A%^K$hv#C7RAVrAxOZgzjUyYvdSNl1=wKLN+cZt9>2+4YPOgLq*WY@qBF0LP zzO}>EA{37@2$!P)NnQmWUb3?z-eEDM2^(Hgz2XIxDonZd0U&BZ>{ZNs>580i&2Jb7 z=UydKiK@ui5p%-G0jY&<6UGkpLQS_0W6+{Bz&^_Bdz3v;2_2Qt8v^NtqZT59>k5q3 z{Nr3i1c}tkj_&r<$=9=$Gdh=@Q)cXH%7OS>jK_QHK$_wN$qA<}@G+6&SG{SUIId8; zdl{GBc=}s>mDL|4DjR)u!|-L?Cgs?zxC7epFbnBKZecT1fY)E2Pil38k0M|JsYyO# z=!MO2qxrFA-JVt1=SASoF}?gvw5ttD6Olht0L1gUiq5CV5Dhi|c=-@_NnLcIh zh=hn*Kx5{EciNKlaf|+!=)xqWiHd^4RW)nI2wwTYLF|)o>bSdWny=%r<03tb5-tCl zxmj15Cw8EcUQp(u{+_vdR#rdS=>H}zC~HBVq+f|Ee^@+$P~gQ;B1hNhDVh!AT$3cN z51frTP&q%EV?*_-i<}rPa^U4*F5=TjCLDt`l1>@UQBO#VtWnAto|sv6uaJsH^`-Hx zfjK+(A=5q?csA?2H!A8&Mh1^@S`|39$bxO?T@0saMzE_iUHcsUoV`*xn*vb8TV?V* z@%@|^P*g}!pWE77cb;yEc+Eptl8(m%Sj@#ez9y%;R~68k+8~Z(PMTIGzb#PRyA`~L z_YnqBQ{G_3R@V*OWlyqQQr8W7PsEXoysPJZFr6+rqQkH$rEr$+b#&AcjAqyR#y-c+ zre|n4m_?bO(=ly|BaAsBP#&*7b?^cj?=0i8o&CLyk1myOH~YabT{X&B zy0^^_H)Z;$FDFS!@zNU#)xEf4`>54*ypy6!JHAQdQIT6DS11cUZFNoljXC7 znDvNQ5qXc}a(l}~M@_4t?6cI;`O2|#*ykb3VM3F$VXUhu0@A`qaicOhGVC`fk?ou+ zqpv?0GKjgnYFg$P-=rLqbzH-&)^kGSt0Wz&0D~@RK~S6#TpCC62X+c8`rKuwmUMLO zKI5ub+=ujEo7Zt8+i0fy9LgK7PPtqyAIM2ey71gFIY^iBVS@OwrfJ15DpNma$BIMZ z)wn&NJJk8G4_ih#q-Ce7^X}~#vKv;01cH{SbIwRdB9K4)P3@r!K-dqd36l2^h}4E9 zZ7~V5a)*9dZnk`MB;|N--^cl{S!nl$+qoT7LJi79Vo(oBBUGnE#rl{>n$N zkdg8rklY1k<$h(U&BQY4n_NFyt|W~ej|6f(zNomA!GM~X>2mXC4xQaLb>QQzd_$A3 zur_mLu1Q+HnH(+=5}yo=`|Z6MWKdUk8w2K8D-mAJ;+CjOXO{&0$v#G5h7bo+aF%89 z+z>9k>Sv~y0Woeh8iN$OibHd%$#)-{rmtJT7o+o$y**uV@#XGc19>JNm{*`XmJ9NO;OjqJOn5AUTARPxB5;V8py$MYU()cms{Y*k zmjw>xB>yD%bD6Z?2@XJq{B6;+r@*HRM*V^kg48!Z-_ZYV-uo2(r|0i4Fc?@INS^Z( z{=YZ?KV^FA(fW&vh462tKO9@1;-8vd{=(ydR+jsDCcj%@K7~KE75oK%Ap7m`f136QqJWBsvi$Ant zPw`JRD!=ew<^OXP{ztL$6#R4$=ok2l{@>syLqbm(o(^;TVz@B)o52{g+UfrcdOXGd z`RMoy4O&3a7!2$m50X#efA-&hhbNl;2LHP^{}laapXztCu=#K3zix6rdRR{h{=6Oj hPA~xYJq7;l<|ro#{lfTK`#(BWS%?4t literal 0 HcmV?d00001 diff --git a/web/src/main/resources/documents/h2020_dataset.docx b/web/src/main/resources/documents/h2020_dataset.docx new file mode 100644 index 0000000000000000000000000000000000000000..4963e3c18449df7981886f8ea392fecc25523d39 GIT binary patch literal 20315 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 literal 0 HcmV?d00001 diff --git a/web/src/main/resources/documents/styles.xml b/web/src/main/resources/documents/styles.xml new file mode 100644 index 0000000..4e78e69 --- /dev/null +++ b/web/src/main/resources/documents/styles.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/web/src/main/resources/documents/~$020_dataset.docx b/web/src/main/resources/documents/~$020_dataset.docx new file mode 100644 index 0000000000000000000000000000000000000000..697818f3e6c56ca4d8e5fec8bc9360989e54e016 GIT binary patch literal 162 zcmWeW_3-t>Hy{4Idj3h_@Y8=EAHRJ6iGd&xW|+mik$E=|?_oZ`e1>@!^LFM#%nA&X znYS{ZV?M~dnRzGkexL}*QbAy?LBB8P!rMqV1 + + + currency + xml + internal/iso-4217.xml + eu.eudat.logic.proxy.fetching.entities.CurrencyModel + currencies + currency + code + + + \ No newline at end of file diff --git a/web/src/main/resources/internal/iso-4217.xml b/web/src/main/resources/internal/iso-4217.xml new file mode 100644 index 0000000..5ba6f6b --- /dev/null +++ b/web/src/main/resources/internal/iso-4217.xml @@ -0,0 +1,1949 @@ + + + + + AFGHANISTAN + Afghani + AFN + 971 + 2 + + + ÅLAND ISLANDS + Euro + EUR + 978 + 2 + + + ALBANIA + Lek + ALL + 008 + 2 + + + ALGERIA + Algerian Dinar + DZD + 012 + 2 + + + AMERICAN SAMOA + US Dollar + USD + 840 + 2 + + + ANDORRA + Euro + EUR + 978 + 2 + + + ANGOLA + Kwanza + AOA + 973 + 2 + + + ANGUILLA + East Caribbean Dollar + XCD + 951 + 2 + + + ANTARCTICA + No universal currency + + + ANTIGUA AND BARBUDA + East Caribbean Dollar + XCD + 951 + 2 + + + ARGENTINA + Argentine Peso + ARS + 032 + 2 + + + ARMENIA + Armenian Dram + AMD + 051 + 2 + + + ARUBA + Aruban Florin + AWG + 533 + 2 + + + AUSTRALIA + Australian Dollar + AUD + 036 + 2 + + + AUSTRIA + Euro + EUR + 978 + 2 + + + AZERBAIJAN + Azerbaijan Manat + AZN + 944 + 2 + + + BAHAMAS (THE) + Bahamian Dollar + BSD + 044 + 2 + + + BAHRAIN + Bahraini Dinar + BHD + 048 + 3 + + + BANGLADESH + Taka + BDT + 050 + 2 + + + BARBADOS + Barbados Dollar + BBD + 052 + 2 + + + BELARUS + Belarusian Ruble + BYN + 933 + 2 + + + BELGIUM + Euro + EUR + 978 + 2 + + + BELIZE + Belize Dollar + BZD + 084 + 2 + + + BENIN + CFA Franc BCEAO + XOF + 952 + 0 + + + BERMUDA + Bermudian Dollar + BMD + 060 + 2 + + + BHUTAN + Indian Rupee + INR + 356 + 2 + + + BHUTAN + Ngultrum + BTN + 064 + 2 + + + BOLIVIA (PLURINATIONAL STATE OF) + Boliviano + BOB + 068 + 2 + + + BOLIVIA (PLURINATIONAL STATE OF) + Mvdol + BOV + 984 + 2 + + + BONAIRE, SINT EUSTATIUS AND SABA + US Dollar + USD + 840 + 2 + + + BOSNIA AND HERZEGOVINA + Convertible Mark + BAM + 977 + 2 + + + BOTSWANA + Pula + BWP + 072 + 2 + + + BOUVET ISLAND + Norwegian Krone + NOK + 578 + 2 + + + BRAZIL + Brazilian Real + BRL + 986 + 2 + + + BRITISH INDIAN OCEAN TERRITORY (THE) + US Dollar + USD + 840 + 2 + + + BRUNEI DARUSSALAM + Brunei Dollar + BND + 096 + 2 + + + BULGARIA + Bulgarian Lev + BGN + 975 + 2 + + + BURKINA FASO + CFA Franc BCEAO + XOF + 952 + 0 + + + BURUNDI + Burundi Franc + BIF + 108 + 0 + + + CABO VERDE + Cabo Verde Escudo + CVE + 132 + 2 + + + CAMBODIA + Riel + KHR + 116 + 2 + + + CAMEROON + CFA Franc BEAC + XAF + 950 + 0 + + + CANADA + Canadian Dollar + CAD + 124 + 2 + + + CAYMAN ISLANDS (THE) + Cayman Islands Dollar + KYD + 136 + 2 + + + CENTRAL AFRICAN REPUBLIC (THE) + CFA Franc BEAC + XAF + 950 + 0 + + + CHAD + CFA Franc BEAC + XAF + 950 + 0 + + + CHILE + Chilean Peso + CLP + 152 + 0 + + + CHILE + Unidad de Fomento + CLF + 990 + 4 + + + CHINA + Yuan Renminbi + CNY + 156 + 2 + + + CHRISTMAS ISLAND + Australian Dollar + AUD + 036 + 2 + + + COCOS (KEELING) ISLANDS (THE) + Australian Dollar + AUD + 036 + 2 + + + COLOMBIA + Colombian Peso + COP + 170 + 2 + + + COLOMBIA + Unidad de Valor Real + COU + 970 + 2 + + + COMOROS (THE) + Comorian Franc + KMF + 174 + 0 + + + CONGO (THE DEMOCRATIC REPUBLIC OF THE) + Congolese Franc + CDF + 976 + 2 + + + CONGO (THE) + CFA Franc BEAC + XAF + 950 + 0 + + + COOK ISLANDS (THE) + New Zealand Dollar + NZD + 554 + 2 + + + COSTA RICA + Costa Rican Colon + CRC + 188 + 2 + + + CÔTE D'IVOIRE + CFA Franc BCEAO + XOF + 952 + 0 + + + CROATIA + Kuna + HRK + 191 + 2 + + + CUBA + Cuban Peso + CUP + 192 + 2 + + + CUBA + Peso Convertible + CUC + 931 + 2 + + + CURAÇAO + Netherlands Antillean Guilder + ANG + 532 + 2 + + + CYPRUS + Euro + EUR + 978 + 2 + + + CZECHIA + Czech Koruna + CZK + 203 + 2 + + + DENMARK + Danish Krone + DKK + 208 + 2 + + + DJIBOUTI + Djibouti Franc + DJF + 262 + 0 + + + DOMINICA + East Caribbean Dollar + XCD + 951 + 2 + + + DOMINICAN REPUBLIC (THE) + Dominican Peso + DOP + 214 + 2 + + + ECUADOR + US Dollar + USD + 840 + 2 + + + EGYPT + Egyptian Pound + EGP + 818 + 2 + + + EL SALVADOR + El Salvador Colon + SVC + 222 + 2 + + + EL SALVADOR + US Dollar + USD + 840 + 2 + + + EQUATORIAL GUINEA + CFA Franc BEAC + XAF + 950 + 0 + + + ERITREA + Nakfa + ERN + 232 + 2 + + + ESTONIA + Euro + EUR + 978 + 2 + + + ESWATINI + Lilangeni + SZL + 748 + 2 + + + ETHIOPIA + Ethiopian Birr + ETB + 230 + 2 + + + EUROPEAN UNION + Euro + EUR + 978 + 2 + + + FALKLAND ISLANDS (THE) [MALVINAS] + Falkland Islands Pound + FKP + 238 + 2 + + + FAROE ISLANDS (THE) + Danish Krone + DKK + 208 + 2 + + + FIJI + Fiji Dollar + FJD + 242 + 2 + + + FINLAND + Euro + EUR + 978 + 2 + + + FRANCE + Euro + EUR + 978 + 2 + + + FRENCH GUIANA + Euro + EUR + 978 + 2 + + + FRENCH POLYNESIA + CFP Franc + XPF + 953 + 0 + + + FRENCH SOUTHERN TERRITORIES (THE) + Euro + EUR + 978 + 2 + + + GABON + CFA Franc BEAC + XAF + 950 + 0 + + + GAMBIA (THE) + Dalasi + GMD + 270 + 2 + + + GEORGIA + Lari + GEL + 981 + 2 + + + GERMANY + Euro + EUR + 978 + 2 + + + GHANA + Ghana Cedi + GHS + 936 + 2 + + + GIBRALTAR + Gibraltar Pound + GIP + 292 + 2 + + + GREECE + Euro + EUR + 978 + 2 + + + GREENLAND + Danish Krone + DKK + 208 + 2 + + + GRENADA + East Caribbean Dollar + XCD + 951 + 2 + + + GUADELOUPE + Euro + EUR + 978 + 2 + + + GUAM + US Dollar + USD + 840 + 2 + + + GUATEMALA + Quetzal + GTQ + 320 + 2 + + + GUERNSEY + Pound Sterling + GBP + 826 + 2 + + + GUINEA + Guinean Franc + GNF + 324 + 0 + + + GUINEA-BISSAU + CFA Franc BCEAO + XOF + 952 + 0 + + + GUYANA + Guyana Dollar + GYD + 328 + 2 + + + HAITI + Gourde + HTG + 332 + 2 + + + HAITI + US Dollar + USD + 840 + 2 + + + HEARD ISLAND AND McDONALD ISLANDS + Australian Dollar + AUD + 036 + 2 + + + HOLY SEE (THE) + Euro + EUR + 978 + 2 + + + HONDURAS + Lempira + HNL + 340 + 2 + + + HONG KONG + Hong Kong Dollar + HKD + 344 + 2 + + + HUNGARY + Forint + HUF + 348 + 2 + + + ICELAND + Iceland Krona + ISK + 352 + 0 + + + INDIA + Indian Rupee + INR + 356 + 2 + + + INDONESIA + Rupiah + IDR + 360 + 2 + + + INTERNATIONAL MONETARY FUND (IMF)  + SDR (Special Drawing Right) + XDR + 960 + N.A. + + + IRAN (ISLAMIC REPUBLIC OF) + Iranian Rial + IRR + 364 + 2 + + + IRAQ + Iraqi Dinar + IQD + 368 + 3 + + + IRELAND + Euro + EUR + 978 + 2 + + + ISLE OF MAN + Pound Sterling + GBP + 826 + 2 + + + ISRAEL + New Israeli Sheqel + ILS + 376 + 2 + + + ITALY + Euro + EUR + 978 + 2 + + + JAMAICA + Jamaican Dollar + JMD + 388 + 2 + + + JAPAN + Yen + JPY + 392 + 0 + + + JERSEY + Pound Sterling + GBP + 826 + 2 + + + JORDAN + Jordanian Dinar + JOD + 400 + 3 + + + KAZAKHSTAN + Tenge + KZT + 398 + 2 + + + KENYA + Kenyan Shilling + KES + 404 + 2 + + + KIRIBATI + Australian Dollar + AUD + 036 + 2 + + + KOREA (THE DEMOCRATIC PEOPLE’S REPUBLIC OF) + North Korean Won + KPW + 408 + 2 + + + KOREA (THE REPUBLIC OF) + Won + KRW + 410 + 0 + + + KUWAIT + Kuwaiti Dinar + KWD + 414 + 3 + + + KYRGYZSTAN + Som + KGS + 417 + 2 + + + LAO PEOPLE’S DEMOCRATIC REPUBLIC (THE) + Lao Kip + LAK + 418 + 2 + + + LATVIA + Euro + EUR + 978 + 2 + + + LEBANON + Lebanese Pound + LBP + 422 + 2 + + + LESOTHO + Loti + LSL + 426 + 2 + + + LESOTHO + Rand + ZAR + 710 + 2 + + + LIBERIA + Liberian Dollar + LRD + 430 + 2 + + + LIBYA + Libyan Dinar + LYD + 434 + 3 + + + LIECHTENSTEIN + Swiss Franc + CHF + 756 + 2 + + + LITHUANIA + Euro + EUR + 978 + 2 + + + LUXEMBOURG + Euro + EUR + 978 + 2 + + + MACAO + Pataca + MOP + 446 + 2 + + + MACEDONIA (THE FORMER YUGOSLAV REPUBLIC OF) + Denar + MKD + 807 + 2 + + + MADAGASCAR + Malagasy Ariary + MGA + 969 + 2 + + + MALAWI + Malawi Kwacha + MWK + 454 + 2 + + + MALAYSIA + Malaysian Ringgit + MYR + 458 + 2 + + + MALDIVES + Rufiyaa + MVR + 462 + 2 + + + MALI + CFA Franc BCEAO + XOF + 952 + 0 + + + MALTA + Euro + EUR + 978 + 2 + + + MARSHALL ISLANDS (THE) + US Dollar + USD + 840 + 2 + + + MARTINIQUE + Euro + EUR + 978 + 2 + + + MAURITANIA + Ouguiya + MRU + 929 + 2 + + + MAURITIUS + Mauritius Rupee + MUR + 480 + 2 + + + MAYOTTE + Euro + EUR + 978 + 2 + + + MEMBER COUNTRIES OF THE AFRICAN DEVELOPMENT BANK GROUP + ADB Unit of Account + XUA + 965 + N.A. + + + MEXICO + Mexican Peso + MXN + 484 + 2 + + + MEXICO + Mexican Unidad de Inversion (UDI) + MXV + 979 + 2 + + + MICRONESIA (FEDERATED STATES OF) + US Dollar + USD + 840 + 2 + + + MOLDOVA (THE REPUBLIC OF) + Moldovan Leu + MDL + 498 + 2 + + + MONACO + Euro + EUR + 978 + 2 + + + MONGOLIA + Tugrik + MNT + 496 + 2 + + + MONTENEGRO + Euro + EUR + 978 + 2 + + + MONTSERRAT + East Caribbean Dollar + XCD + 951 + 2 + + + MOROCCO + Moroccan Dirham + MAD + 504 + 2 + + + MOZAMBIQUE + Mozambique Metical + MZN + 943 + 2 + + + MYANMAR + Kyat + MMK + 104 + 2 + + + NAMIBIA + Namibia Dollar + NAD + 516 + 2 + + + NAMIBIA + Rand + ZAR + 710 + 2 + + + NAURU + Australian Dollar + AUD + 036 + 2 + + + NEPAL + Nepalese Rupee + NPR + 524 + 2 + + + NETHERLANDS (THE) + Euro + EUR + 978 + 2 + + + NEW CALEDONIA + CFP Franc + XPF + 953 + 0 + + + NEW ZEALAND + New Zealand Dollar + NZD + 554 + 2 + + + NICARAGUA + Cordoba Oro + NIO + 558 + 2 + + + NIGER (THE) + CFA Franc BCEAO + XOF + 952 + 0 + + + NIGERIA + Naira + NGN + 566 + 2 + + + NIUE + New Zealand Dollar + NZD + 554 + 2 + + + NORFOLK ISLAND + Australian Dollar + AUD + 036 + 2 + + + NORTHERN MARIANA ISLANDS (THE) + US Dollar + USD + 840 + 2 + + + NORWAY + Norwegian Krone + NOK + 578 + 2 + + + OMAN + Rial Omani + OMR + 512 + 3 + + + PAKISTAN + Pakistan Rupee + PKR + 586 + 2 + + + PALAU + US Dollar + USD + 840 + 2 + + + PALESTINE, STATE OF + No universal currency + + + PANAMA + Balboa + PAB + 590 + 2 + + + PANAMA + US Dollar + USD + 840 + 2 + + + PAPUA NEW GUINEA + Kina + PGK + 598 + 2 + + + PARAGUAY + Guarani + PYG + 600 + 0 + + + PERU + Sol + PEN + 604 + 2 + + + PHILIPPINES (THE) + Philippine Peso + PHP + 608 + 2 + + + PITCAIRN + New Zealand Dollar + NZD + 554 + 2 + + + POLAND + Zloty + PLN + 985 + 2 + + + PORTUGAL + Euro + EUR + 978 + 2 + + + PUERTO RICO + US Dollar + USD + 840 + 2 + + + QATAR + Qatari Rial + QAR + 634 + 2 + + + RÉUNION + Euro + EUR + 978 + 2 + + + ROMANIA + Romanian Leu + RON + 946 + 2 + + + RUSSIAN FEDERATION (THE) + Russian Ruble + RUB + 643 + 2 + + + RWANDA + Rwanda Franc + RWF + 646 + 0 + + + SAINT BARTHÉLEMY + Euro + EUR + 978 + 2 + + + SAINT HELENA, ASCENSION AND TRISTAN DA CUNHA + Saint Helena Pound + SHP + 654 + 2 + + + SAINT KITTS AND NEVIS + East Caribbean Dollar + XCD + 951 + 2 + + + SAINT LUCIA + East Caribbean Dollar + XCD + 951 + 2 + + + SAINT MARTIN (FRENCH PART) + Euro + EUR + 978 + 2 + + + SAINT PIERRE AND MIQUELON + Euro + EUR + 978 + 2 + + + SAINT VINCENT AND THE GRENADINES + East Caribbean Dollar + XCD + 951 + 2 + + + SAMOA + Tala + WST + 882 + 2 + + + SAN MARINO + Euro + EUR + 978 + 2 + + + SAO TOME AND PRINCIPE + Dobra + STN + 930 + 2 + + + SAUDI ARABIA + Saudi Riyal + SAR + 682 + 2 + + + SENEGAL + CFA Franc BCEAO + XOF + 952 + 0 + + + SERBIA + Serbian Dinar + RSD + 941 + 2 + + + SEYCHELLES + Seychelles Rupee + SCR + 690 + 2 + + + SIERRA LEONE + Leone + SLL + 694 + 2 + + + SINGAPORE + Singapore Dollar + SGD + 702 + 2 + + + SINT MAARTEN (DUTCH PART) + Netherlands Antillean Guilder + ANG + 532 + 2 + + + SISTEMA UNITARIO DE COMPENSACION REGIONAL DE PAGOS "SUCRE" + Sucre + XSU + 994 + N.A. + + + SLOVAKIA + Euro + EUR + 978 + 2 + + + SLOVENIA + Euro + EUR + 978 + 2 + + + SOLOMON ISLANDS + Solomon Islands Dollar + SBD + 090 + 2 + + + SOMALIA + Somali Shilling + SOS + 706 + 2 + + + SOUTH AFRICA + Rand + ZAR + 710 + 2 + + + SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS + No universal currency + + + SOUTH SUDAN + South Sudanese Pound + SSP + 728 + 2 + + + SPAIN + Euro + EUR + 978 + 2 + + + SRI LANKA + Sri Lanka Rupee + LKR + 144 + 2 + + + SUDAN (THE) + Sudanese Pound + SDG + 938 + 2 + + + SURINAME + Surinam Dollar + SRD + 968 + 2 + + + SVALBARD AND JAN MAYEN + Norwegian Krone + NOK + 578 + 2 + + + SWEDEN + Swedish Krona + SEK + 752 + 2 + + + SWITZERLAND + Swiss Franc + CHF + 756 + 2 + + + SWITZERLAND + WIR Euro + CHE + 947 + 2 + + + SWITZERLAND + WIR Franc + CHW + 948 + 2 + + + SYRIAN ARAB REPUBLIC + Syrian Pound + SYP + 760 + 2 + + + TAIWAN (PROVINCE OF CHINA) + New Taiwan Dollar + TWD + 901 + 2 + + + TAJIKISTAN + Somoni + TJS + 972 + 2 + + + TANZANIA, UNITED REPUBLIC OF + Tanzanian Shilling + TZS + 834 + 2 + + + THAILAND + Baht + THB + 764 + 2 + + + TIMOR-LESTE + US Dollar + USD + 840 + 2 + + + TOGO + CFA Franc BCEAO + XOF + 952 + 0 + + + TOKELAU + New Zealand Dollar + NZD + 554 + 2 + + + TONGA + Pa’anga + TOP + 776 + 2 + + + TRINIDAD AND TOBAGO + Trinidad and Tobago Dollar + TTD + 780 + 2 + + + TUNISIA + Tunisian Dinar + TND + 788 + 3 + + + TURKEY + Turkish Lira + TRY + 949 + 2 + + + TURKMENISTAN + Turkmenistan New Manat + TMT + 934 + 2 + + + TURKS AND CAICOS ISLANDS (THE) + US Dollar + USD + 840 + 2 + + + TUVALU + Australian Dollar + AUD + 036 + 2 + + + UGANDA + Uganda Shilling + UGX + 800 + 0 + + + UKRAINE + Hryvnia + UAH + 980 + 2 + + + UNITED ARAB EMIRATES (THE) + UAE Dirham + AED + 784 + 2 + + + UNITED KINGDOM OF GREAT BRITAIN AND NORTHERN IRELAND (THE) + Pound Sterling + GBP + 826 + 2 + + + UNITED STATES MINOR OUTLYING ISLANDS (THE) + US Dollar + USD + 840 + 2 + + + UNITED STATES OF AMERICA (THE) + US Dollar + USD + 840 + 2 + + + UNITED STATES OF AMERICA (THE) + US Dollar (Next day) + USN + 997 + 2 + + + URUGUAY + Peso Uruguayo + UYU + 858 + 2 + + + URUGUAY + Uruguay Peso en Unidades Indexadas (UI) + UYI + 940 + 0 + + + URUGUAY + Unidad Previsional + UYW + 927 + 4 + + + UZBEKISTAN + Uzbekistan Sum + UZS + 860 + 2 + + + VANUATU + Vatu + VUV + 548 + 0 + + + VENEZUELA (BOLIVARIAN REPUBLIC OF) + Bolívar Soberano + VES + 928 + 2 + + + VIET NAM + Dong + VND + 704 + 0 + + + VIRGIN ISLANDS (BRITISH) + US Dollar + USD + 840 + 2 + + + VIRGIN ISLANDS (U.S.) + US Dollar + USD + 840 + 2 + + + WALLIS AND FUTUNA + CFP Franc + XPF + 953 + 0 + + + WESTERN SAHARA + Moroccan Dirham + MAD + 504 + 2 + + + YEMEN + Yemeni Rial + YER + 886 + 2 + + + ZAMBIA + Zambian Kwacha + ZMW + 967 + 2 + + + ZIMBABWE + Zimbabwe Dollar + ZWL + 932 + 2 + + + ZZ01_Bond Markets Unit European_EURCO + Bond Markets Unit European Composite Unit (EURCO) + XBA + 955 + N.A. + + + ZZ02_Bond Markets Unit European_EMU-6 + Bond Markets Unit European Monetary Unit (E.M.U.-6) + XBB + 956 + N.A. + + + ZZ03_Bond Markets Unit European_EUA-9 + Bond Markets Unit European Unit of Account 9 (E.U.A.-9) + XBC + 957 + N.A. + + + ZZ04_Bond Markets Unit European_EUA-17 + Bond Markets Unit European Unit of Account 17 (E.U.A.-17) + XBD + 958 + N.A. + + + ZZ06_Testing_Code + Codes specifically reserved for testing purposes + XTS + 963 + N.A. + + + ZZ07_No_Currency + The codes assigned for transactions where no currency is involved + XXX + 999 + N.A. + + + ZZ08_Gold + Gold + XAU + 959 + N.A. + + + ZZ09_Palladium + Palladium + XPD + 964 + N.A. + + + ZZ10_Platinum + Platinum + XPT + 962 + N.A. + + + ZZ11_Silver + Silver + XAG + 961 + N.A. + + + \ No newline at end of file diff --git a/web/src/main/resources/internal/rda-lang-map.json b/web/src/main/resources/internal/rda-lang-map.json new file mode 100644 index 0000000..794787f --- /dev/null +++ b/web/src/main/resources/internal/rda-lang-map.json @@ -0,0 +1,186 @@ +{ + "aar": "aa", + "abk": "ab", + "afr": "af", + "aka": "ak", + "amh": "am", + "ara": "ar", + "arg": "an", + "asm": "as", + "ava": "av", + "ave": "ae", + "aym": "ay", + "aze": "az", + "bak": "ba", + "bam": "bm", + "bel": "be", + "ben": "bn", + "bis": "bi", + "bod": "bo", + "bos": "bs", + "bre": "br", + "bul": "bg", + "cat": "ca", + "ces": "cs", + "cha": "ch", + "che": "ce", + "chu": "cu", + "chv": "cv", + "cor": "kw", + "cos": "co", + "cre": "cr", + "cym": "cy", + "dan": "da", + "deu": "de", + "div": "dv", + "dzo": "dz", + "ell": "el", + "eng": "en", + "epo": "eo", + "est": "et", + "eus": "eu", + "ewe": "ee", + "fao": "fo", + "fas": "fa", + "fij": "fj", + "fin": "fi", + "fra": "fr", + "fry": "fy", + "ful": "ff", + "gla": "gd", + "gle": "ga", + "glg": "gl", + "glv": "gv", + "grn": "gn", + "guj": "gu", + "hat": "ht", + "hau": "ha", + "hbs": "sh", + "heb": "he", + "her": "hz", + "hin": "hi", + "hmo": "ho", + "hrv": "hr", + "hun": "hu", + "hye": "hy", + "ibo": "ig", + "ido": "io", + "iii": "ii", + "iku": "iu", + "ile": "ie", + "ina": "ia", + "ind": "id", + "ipk": "ik", + "isl": "is", + "ita": "it", + "jav": "jv", + "jpn": "ja", + "kal": "kl", + "kan": "kn", + "kas": "ks", + "kat": "ka", + "kau": "kr", + "kaz": "kk", + "khm": "km", + "kik": "ki", + "kin": "rw", + "kir": "ky", + "kom": "kv", + "kon": "kg", + "kor": "ko", + "kua": "kj", + "kur": "ku", + "lao": "lo", + "lat": "la", + "lav": "lv", + "lim": "li", + "lin": "ln", + "lit": "lt", + "ltz": "lb", + "lub": "lu", + "lug": "lg", + "mah": "mh", + "mal": "ml", + "mar": "mr", + "mkd": "mk", + "mlg": "mg", + "mlt": "mt", + "mon": "mn", + "mri": "mi", + "msa": "ms", + "mya": "my", + "nau": "na", + "nav": "nv", + "nbl": "nr", + "nde": "nd", + "ndo": "ng", + "nep": "ne", + "nld": "nl", + "nno": "nn", + "nob": "nb", + "nor": "no", + "nya": "ny", + "oci": "oc", + "oji": "oj", + "ori": "or", + "orm": "om", + "oss": "os", + "pan": "pa", + "pli": "pi", + "pol": "pl", + "por": "pt", + "pus": "ps", + "que": "qu", + "roh": "rm", + "ron": "ro", + "run": "rn", + "rus": "ru", + "sag": "sg", + "san": "sa", + "sin": "si", + "slk": "sk", + "slv": "sl", + "sme": "se", + "smo": "sm", + "sna": "sn", + "snd": "sd", + "som": "so", + "sot": "st", + "spa": "es", + "sqi": "sq", + "srd": "sc", + "srp": "sr", + "ssw": "ss", + "sun": "su", + "swa": "sw", + "swe": "sv", + "tah": "ty", + "tam": "ta", + "tat": "tt", + "tel": "te", + "tgk": "tg", + "tgl": "tl", + "tha": "th", + "tir": "ti", + "ton": "to", + "tsn": "tn", + "tso": "ts", + "tuk": "tk", + "tur": "tr", + "twi": "tw", + "uig": "ug", + "ukr": "uk", + "urd": "ur", + "uzb": "uz", + "ven": "ve", + "vie": "vi", + "vol": "vo", + "wln": "wa", + "wol": "wo", + "xho": "xh", + "yid": "yi", + "yor": "yo", + "zha": "za", + "zho": "zh", + "zul": "zu" +} \ No newline at end of file diff --git a/web/src/main/resources/pidLinks.json b/web/src/main/resources/pidLinks.json new file mode 100644 index 0000000..d2a0116 --- /dev/null +++ b/web/src/main/resources/pidLinks.json @@ -0,0 +1,100 @@ +{ + "pidLinks": [ + { + "pid": "doi", + "link": "https://doi.org/{pid}" + }, + { + "pid": "uniprot", + "link": "https://uniprot.org/uniprotkb/{pid}" + }, + { + "pid": "handle", + "link": "https://hdl.handle.net/{pid}" + }, + { + "pid": "arxiv", + "link": "https://arxiv.org/abs/{pid}" + }, + { + "pid": "ascl", + "link": "https://ascl.net/{pid}" + }, + { + "pid": "orcid", + "link": "https://orcid.org/{pid}" + }, + { + "pid": "pmid", + "link": "https://pubmed.ncbi.nlm.nih.gov/{pid}" + }, + { + "pid": "ads", + "link": "https://ui.adsabs.harvard.edu/#abs/{pid}" + }, + { + "pid": "pmcid", + "link": "https://ncbi.nlm.nih.gov/pmc/{pid}" + }, + { + "pid": "gnd", + "link": "https://d-nb.info/gnd/{pid}" + }, + { + "pid": "urn", + "link": "https://nbn-resolving.org/{pid}" + }, + { + "pid": "sra", + "link": "https://ebi.ac.uk/ena/data/view/{pid}" + }, + { + "pid": "bioproject", + "link": "https://ebi.ac.uk/ena/data/view/{pid}" + }, + { + "pid": "biosample", + "link": "https://ebi.ac.uk/ena/data/view/{pid}" + }, + { + "pid": "ensembl", + "link": "https://ensembl.org/id/{pid}" + }, + { + "pid": "refseq", + "link": "https://ncbi.nlm.nih.gov/entrez/viewer.fcgi?val={pid}" + }, + { + "pid": "genome", + "link": "https://ncbi.nlm.nih.gov/assembly/{pid}" + }, + { + "pid": "geo", + "link": "https://ncbi.nlm.nih.gov/geo/query/acc.cgi?acc={pid}" + }, + { + "pid": "arrayexpress_array", + "link": "https://ebi.ac.uk/arrayexpress/arrays/{pid}" + }, + { + "pid": "arrayexpress_experiment", + "link": "https://ebi.ac.uk/arrayexpress/experiments/{pid}" + }, + { + "pid": "hal", + "link": "https://hal.archives-ouvertes.fr/{pid}" + }, + { + "pid": "swh", + "link": "https://archive.softwareheritage.org/{pid}" + }, + { + "pid": "ror", + "link": "https://ror.org/{pid}" + }, + { + "pid": "viaf", + "link": "https://viaf.org/viaf/{pid}" + } + ] +} \ No newline at end of file