From 624e6e4c2ca5f4a91af6be4e32bac6040ce436a9 Mon Sep 17 00:00:00 2001 From: theresa Date: Mon, 29 Jul 2024 11:49:44 +0200 Subject: [PATCH 01/33] #3303 added pid field to variable class --- .../configuration/translations-de.js | 4 ++ .../configuration/translations-en.js | 4 ++ .../common/domain/util/Patterns.java | 1 + .../variablemanagement/domain/Variable.java | 45 ++++++++++++------- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js index adc1fac40b4..4e06cbb0218 100644 --- a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js +++ b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js @@ -308,6 +308,10 @@ angular.module('metadatamanagementApp').config([ 'variable-has-invalid-data-set-id': 'Die Variable {{id}} referenziert auf einen unbekannten Datensatz ({{toBereferenzedId}}).', 'variable-has-invalid-question-id': 'Die Variable {{id}} referenziert auf einen unbekannte Frage ({{toBereferenzedId}}).', 'variable-survey-ids-are-not-consistent-with-data-set': 'Die Variable {{id}} referenziert auf andere Erhebungen als ihr Datensatz {{toBereferenzedId}}.' + }, + "pid": { + "pattern": "Der angegebene Wert stimmt nicht mit dem benötigten Format der PID überein.", + "size": "Der angegebene Wert darf nicht länger als 512 Zeichen sein." } }, 'edit': { diff --git a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js index 2fa29936859..ebbff235cb2 100644 --- a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js +++ b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js @@ -308,6 +308,10 @@ angular.module('metadatamanagementApp').config([ 'variable-has-invalid-data-set-id': 'The Variable {{id}} references to an unknown Data Set ({{toBereferenzedId}}).', 'variable-has-invalid-question-id': 'The Variable {{id}} references to an unknown Question ({{toBereferenzedId}}).', 'variable-survey-ids-are-not-consistent-with-data-set': 'The Variable {{id}} references different surveys than its Data Set {{toBereferenzedId}}.' + }, + "pid": { + "pattern": "The provided value does not match the PID pattern.", + "size": "The provided value must not contain more than 512 characters." } }, 'edit': { diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/common/domain/util/Patterns.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/common/domain/util/Patterns.java index 79f9b27b060..ffd3b7162e3 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/common/domain/util/Patterns.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/common/domain/util/Patterns.java @@ -15,6 +15,7 @@ public interface Patterns { String GERMAN_ALPHANUMERIC_WITH_UNDERSCORE_AND_MINUS_AND_DOT = "^[_A-Za-z0-9äöüÄÖÜß\\-\\.]*$"; String DOI = "^https:\\/\\/doi.org\\/([_A-Za-z0-9äöüÄÖÜß\\-\\/\\:.]{1,}$)"; + String PID = "^21\\.T11998\\/dzhw:([_A-Za-z0-9äöüÄÖÜß\\-\\/\\:.]{1,}$)"; String GERMAN_ALPHANUMERIC_WITH_UNDERSCORE_AND_MINUS_AND_DOT_AND_DOLLAR = "^[_A-Za-z0-9äöüÄÖÜß\\-\\.\\$]*$"; String NO_WHITESPACE = "^[^\\s]*$"; diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java index b1fde177665..7e63b8411ee 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java @@ -117,7 +117,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The id of the variable which uniquely identifies the variable in this application. - * + * * The id must not be empty and must be of the form * var-{{dataAcquisitionProjectId}}-ds{{dataSetNumber}}-{{name}}$. The id must not contain more * than 512 characters. @@ -134,9 +134,22 @@ public class Variable extends AbstractShadowableRdcDomainObject { @Indexed private String masterId; + /** + * The PID of the variable. + * + * Must not contain more than 512 characters. + * + * Must match the pattern of a PID "21.T11998/dzhw:{DataPackageID}_{VariableID}:{version} + */ + @Size(max = StringLengths.MEDIUM, message = "variable-management.error.pid.size") + @Pattern( + message = "variable-management.error.pid.pattern", + regexp = Patterns.PID) + private String pid; + /** * The id of the {@link DataAcquisitionProject} to which this variable belongs. - * + * * The dataAcquisitionProjectId must not be empty. */ @Indexed @@ -145,7 +158,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The name of the variable as it is used in the {@link DataSet}. - * + * * It must not be empty and must be unique in the {@link DataSet}. It must contain only * alphanumeric (english) characters and "_". The first character must not be a number. It must * not contain more than 32 characters. @@ -158,7 +171,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The label of the variable should describe its content. - * + * * It must be specified in at least one language and it must not contain more than 512 characters. */ @NotNull(message = "variable-management.error.variable.label.not-null") @@ -169,7 +182,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * Arbitrary additional text for this variable. Markdown is supported. - * + * * Must not contain more than 2048 characters. */ @I18nStringSize(max = StringLengths.LARGE, @@ -178,7 +191,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The id of the {@link DataSet} to which this variable belongs. - * + * * Must not be empty. */ @Indexed @@ -187,7 +200,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The number of the {@link DataSet} to which this variable belongs. - * + * * Must not be empty. */ @NotNull(message = "variable-management.error.variable.data-set-number-not-null") @@ -195,7 +208,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The technical type which the {@link ValidResponse}s have. - * + * * Must be one of {@link DataTypes} and must not be empty. */ @NotNull(message = "variable-management.error.variable.data-type.not-null") @@ -205,7 +218,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * Associated with each data type is a storage type. For instance numerics can be stored as * integer or double. - * + * * Must be one of {@link StorageTypes} and must not be empty. */ @NotNull(message = "variable-management.error.variable.storage-type.not-null") @@ -216,7 +229,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { * The scale level (or level of measurement) classifies the nature of information within the * values assigned to this variable ({@link ValidResponse}s). It determines which mathematical * operations can be performed with the values. - * + * * It must be one of {@link ScaleLevels} and must not be empty. If the data type of this variable * is {@link DataTypes#DATE} then the ScaleLevel must be {@link ScaleLevels#ORDINAL}, * {@link ScaleLevels#INTERVAL} or {@link ScaleLevels#NOMINAL}. @@ -228,7 +241,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The access way of this variable. Depends on the sensitivity of the data and describes how the * data user will be able to work with the data. - * + * * Must not be empty and be one of {@link AccessWays}. */ // checks for min size too. @@ -245,7 +258,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * The index in the {@link DataSet} of this variable. Used for sorting the variables of this * {@link DataSet} and for displaying successors and predecessors of this variable. - * + * * Must not be empty and the successor of this variable must have indexInDataSet incremented by * one. */ @@ -254,7 +267,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * List of numbers of {@link Survey}s which have been conducted to create this variable. - * + * * Must not be empty. */ @NotEmpty(message = "variable-management.error.variable.survey-numbers-not-empty") @@ -263,7 +276,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * Identifier used to group variables within this {@link DataSet} which measure the same across * multiple waves. - * + * * Must be of the form {{dataAcquisitionProjectId}}-ds{{dataSetNumber}}-{{string}}$. Must not * contain more than 512 characters and must contain only (german) alphanumeric characters and "_" * and "-". @@ -277,7 +290,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * Identifier used to group variables within this {@link DataSet} which have been derived from * each other. For instance one variable might be an aggregated version of the other. - * + * * Must be of the form {{dataAcquisitionProjectId}}-ds{{dataSetNumber}}-{{string}}$. Must not * contain more than 512 characters and must contain only (german) alphanumeric characters and "_" * and "-". @@ -333,7 +346,7 @@ public class Variable extends AbstractShadowableRdcDomainObject { /** * List of ids of {@link Survey}s which have been conducted to create this variable. - * + * * Must not be empty. */ @Indexed From e326ea3991f724283d614875e0069abb51afb1e5 Mon Sep 17 00:00:00 2001 From: theresa Date: Mon, 29 Jul 2024 12:10:24 +0200 Subject: [PATCH 02/33] #3303 switched quotation marks --- .../variablemanagement/configuration/translations-de.js | 6 +++--- .../variablemanagement/configuration/translations-en.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js index 4e06cbb0218..f124f9f90b1 100644 --- a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js +++ b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-de.js @@ -309,9 +309,9 @@ angular.module('metadatamanagementApp').config([ 'variable-has-invalid-question-id': 'Die Variable {{id}} referenziert auf einen unbekannte Frage ({{toBereferenzedId}}).', 'variable-survey-ids-are-not-consistent-with-data-set': 'Die Variable {{id}} referenziert auf andere Erhebungen als ihr Datensatz {{toBereferenzedId}}.' }, - "pid": { - "pattern": "Der angegebene Wert stimmt nicht mit dem benötigten Format der PID überein.", - "size": "Der angegebene Wert darf nicht länger als 512 Zeichen sein." + 'pid': { + 'pattern': 'Der angegebene Wert stimmt nicht mit dem benötigten Format der PID überein.', + 'size': 'Der angegebene Wert darf nicht länger als 512 Zeichen sein.' } }, 'edit': { diff --git a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js index ebbff235cb2..a912336b482 100644 --- a/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js +++ b/mdm-frontend/src/app/legacy/variablemanagement/configuration/translations-en.js @@ -309,9 +309,9 @@ angular.module('metadatamanagementApp').config([ 'variable-has-invalid-question-id': 'The Variable {{id}} references to an unknown Question ({{toBereferenzedId}}).', 'variable-survey-ids-are-not-consistent-with-data-set': 'The Variable {{id}} references different surveys than its Data Set {{toBereferenzedId}}.' }, - "pid": { - "pattern": "The provided value does not match the PID pattern.", - "size": "The provided value must not contain more than 512 characters." + 'pid': { + 'pattern': 'The provided value does not match the PID pattern.', + 'size': 'The provided value must not contain more than 512 characters.' } }, 'edit': { From c217c9efcfd6e85e2d09cf365731545a58c80795 Mon Sep 17 00:00:00 2001 From: theresa Date: Mon, 29 Jul 2024 14:48:29 +0200 Subject: [PATCH 03/33] #3303 added REST endpoint for JSON export --- .../ExportAllVariablesResourceController.java | 49 ++++++++++++++++ .../service/VariableManagementService.java | 57 +++++++++++++++---- 2 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java new file mode 100644 index 00000000000..294423242fb --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java @@ -0,0 +1,49 @@ +package eu.dzhw.fdz.metadatamanagement.variablemanagement.rest; + +import java.io.IOException; +import java.rmi.server.ExportException; + +import javax.persistence.PersistenceException; + +import eu.dzhw.fdz.metadatamanagement.projectmanagement.service.DataAcquisitionProjectManagementService; +import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; +import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.VariableManagementService; +import lombok.RequiredArgsConstructor; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/api") +@RequiredArgsConstructor +public class ExportAllVariablesResourceController { + + private final VariableManagementService variablesManagementService; + + /** + * export all variables for PID registration. + * + * @return a JSON file + */ + @PostMapping(value = "/variables/exportAll", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + @Secured(value = {AuthoritiesConstants.ADMIN}) + public ResponseEntity exportAllVariables() { + ResponseEntity response = new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); + try { + response = this.variablesManagementService.exportVariablesAsJSON(); + } catch (PersistenceException | IOException ex) { + return response; + } + + return response; + } + + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index ad331fbf77a..8972a92fc7f 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -1,17 +1,30 @@ package eu.dzhw.fdz.metadatamanagement.variablemanagement.service; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.rmi.server.ExportException; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.springframework.core.io.ByteArrayResource; import org.springframework.data.rest.core.annotation.HandleAfterCreate; import org.springframework.data.rest.core.annotation.HandleAfterDelete; import org.springframework.data.rest.core.annotation.HandleAfterSave; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import eu.dzhw.fdz.metadatamanagement.common.service.CrudService; import eu.dzhw.fdz.metadatamanagement.conceptmanagement.domain.Concept; import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.DataPackage; @@ -31,7 +44,7 @@ /** * Service for managing the domain object/aggregate {@link Variable}. - * + * * @author René Reitmann */ @Service @@ -49,7 +62,7 @@ public class VariableManagementService implements CrudService { /** * Delete all variables when the dataAcquisitionProject was deleted. - * + * * @param dataAcquisitionProject the dataAcquisitionProject which has been deleted. */ @HandleAfterDelete @@ -59,7 +72,7 @@ public void onDataAcquisitionProjectDeleted(DataAcquisitionProject dataAcquisiti /** * Update all variables of the project, when the project is released. - * + * * @param dataAcquisitionProject the changed project */ @HandleAfterSave @@ -72,7 +85,7 @@ public void onDataAcquisitionProjectUpdated(DataAcquisitionProject dataAcquisiti /** * A service method for deletion of variables within a data acquisition project. - * + * * @param dataAcquisitionProjectId the id for to the data acquisition project. */ @Secured(value = {AuthoritiesConstants.PUBLISHER, AuthoritiesConstants.DATA_PROVIDER}) @@ -88,7 +101,7 @@ public void deleteAllVariablesByProjectId(String dataAcquisitionProjectId) { /** * Enqueue update of variable search documents when the data set is changed. - * + * * @param dataSet the updated, created or deleted data set. */ @HandleAfterCreate @@ -102,7 +115,7 @@ public void onDataSetChanged(DataSet dataSet) { /** * Enqueue update of variable search documents when the dataPackage is changed. - * + * * @param dataPackage the updated, created or deleted dataPackage. */ @HandleAfterCreate @@ -116,7 +129,7 @@ public void onDataPackageChanged(DataPackage dataPackage) { /** * Enqueue update of variable search documents when the instrument is changed. - * + * * @param instrument the updated, created or deleted instrument. */ @HandleAfterCreate @@ -130,7 +143,7 @@ public void onInstrumentChanged(Instrument instrument) { /** * Enqueue update of variable search documents when the question is changed. - * + * * @param question the updated, created or deleted question. */ @HandleAfterCreate @@ -144,7 +157,7 @@ public void onQuestionChanged(Question question) { /** * Enqueue update of variable search documents when the survey is updated. - * + * * @param survey the updated, created or deleted survey. */ @HandleAfterCreate @@ -158,7 +171,7 @@ public void onSurveyChanged(Survey survey) { /** * Enqueue update of variable search documents when the concept is changed. - * + * * @param concept the updated, created or deleted concept. */ @HandleAfterCreate @@ -202,4 +215,28 @@ public Optional read(String id) { public Optional readSearchDocument(String id) { return crudHelper.readSearchDocument(id); } + + /** + * Writes all variable data according to the PID metadata schema to a JSON file. + * @return the JSON file + * @throws IOException + */ + public ResponseEntity exportVariablesAsJSON() throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode jsonNode = objectMapper.createArrayNode(); + File tempFile = new File("tempfile.json"); + tempFile.deleteOnExit(); + objectMapper.writeValue(tempFile, jsonNode); + Path path = Paths.get(tempFile.getAbsolutePath()); + try { + ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path)); + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Disposition", "attachment; filename=Variables_PID_MDM_Export.json"); + return ResponseEntity.ok() + .headers(headers) + .body(resource); + } catch (IOException ex) { + return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); + } + } } From c3a59fd89524115d274907d46bca621eda298d32 Mon Sep 17 00:00:00 2001 From: theresa Date: Tue, 30 Jul 2024 08:49:57 +0200 Subject: [PATCH 04/33] #3303 added resource to frontend, added download button in administration panel --- .../configuration/translations-de.js | 6 ++++- .../configuration/translations-en.js | 6 ++++- .../health/health.controller.js | 22 ++++++++++++++++++- .../administration/health/health.html.tmpl | 12 ++++++++++ .../resources/variable.resource.js | 18 +++++++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-) diff --git a/mdm-frontend/src/app/legacy/administration/configuration/translations-de.js b/mdm-frontend/src/app/legacy/administration/configuration/translations-de.js index 461cef8a26a..a8ce48ba5d4 100644 --- a/mdm-frontend/src/app/legacy/administration/configuration/translations-de.js +++ b/mdm-frontend/src/app/legacy/administration/configuration/translations-de.js @@ -26,7 +26,8 @@ angular.module('metadatamanagementApp').config([ 'dara': 'Dara', 'messageBroker': 'Message Broker (für Websockets)', 'rabbit': 'RabbitMQ', - 'seo4Ajax': 'Seo4Ajax (Prerender as a Service)' + 'seo4Ajax': 'Seo4Ajax (Prerender as a Service)', + 'pid': 'PID' }, 'table': { 'service': 'Servicename', @@ -45,6 +46,9 @@ angular.module('metadatamanagementApp').config([ 'update': 'Aktualisieren', 'update-success': 'DARA erfolgreich aktualisiert', 'update-failure': 'Es sind Fehler beim Aktualisieren von DARA aufgetreten! (Siehe Details)' + }, + 'pid': { + 'download': 'Daten herunterladen' } }, 'logs': { diff --git a/mdm-frontend/src/app/legacy/administration/configuration/translations-en.js b/mdm-frontend/src/app/legacy/administration/configuration/translations-en.js index ba947595330..40321dd4978 100644 --- a/mdm-frontend/src/app/legacy/administration/configuration/translations-en.js +++ b/mdm-frontend/src/app/legacy/administration/configuration/translations-en.js @@ -26,7 +26,8 @@ angular.module('metadatamanagementApp').config([ 'dara': 'Dara', 'messageBroker': 'Message Broker (for Websockets)', 'rabbit': 'RabbitMQ', - 'seo4Ajax': 'Seo4Ajax (Prerender as a Service)' + 'seo4Ajax': 'Seo4Ajax (Prerender as a Service)', + 'pid': 'PID' }, 'table': { 'service': 'Service name', @@ -45,6 +46,9 @@ angular.module('metadatamanagementApp').config([ 'update': 'Update', 'update-success': 'DARA update successful', 'update-failure': 'Errors occurred during DARA update! (see details)' + }, + 'pid': { + 'download': 'Download data' } }, 'logs': { diff --git a/mdm-frontend/src/app/legacy/administration/health/health.controller.js b/mdm-frontend/src/app/legacy/administration/health/health.controller.js index 0644a448377..298e1dbee5f 100644 --- a/mdm-frontend/src/app/legacy/administration/health/health.controller.js +++ b/mdm-frontend/src/app/legacy/administration/health/health.controller.js @@ -10,8 +10,9 @@ angular.module('metadatamanagementApp').controller('HealthController', [ 'BreadcrumbService', 'SimpleMessageToastService', 'DaraReleaseCustomResource', + 'ExportAllVariablesResource', function($scope, MonitoringService, $uibModal, ElasticSearchAdminService, - PageMetadataService, $state, BreadcrumbService, SimpleMessageToastService, DaraReleaseCustomResource) { + PageMetadataService, $state, BreadcrumbService, SimpleMessageToastService, DaraReleaseCustomResource, ExportAllVariablesResource) { PageMetadataService.setPageTitle('administration.health.title'); $scope.isRecreatingIndices = false; $scope.updatingHealth = true; @@ -70,6 +71,25 @@ angular.module('metadatamanagementApp').controller('HealthController', [ }); } + /** + * Method to download all variable metadata as needed for PID registration. + * Data will be downloaded as a JSON file. + */ + $scope.downloadPidData = function() { + $scope.isDownloadingData = true; + ExportAllVariablesResource.exportAll().then(function(res) { + var blob = new Blob([angular.toJson(res, true)],{ + type: "application/json;charset=utf-8;" + }); + var downloadLink = document.createElement('a'); + downloadLink.setAttribute('download', 'variable_pid_mdm_export.json'); + downloadLink.setAttribute('href', window.URL.createObjectURL(blob)); + downloadLink.click(); + console.log("Download", res); + $scope.isDownloadingData = false; + }) + } + $scope.refresh(); $scope.getLabelClass = function(statusState) { diff --git a/mdm-frontend/src/app/legacy/administration/health/health.html.tmpl b/mdm-frontend/src/app/legacy/administration/health/health.html.tmpl index c78eb1f9496..99e102c6bd2 100644 --- a/mdm-frontend/src/app/legacy/administration/health/health.html.tmpl +++ b/mdm-frontend/src/app/legacy/administration/health/health.html.tmpl @@ -44,6 +44,18 @@ + + {{'administration.health.indicator.pid' | translate}} + + + + + + + + diff --git a/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js b/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js index cb060358881..f92cff56e9c 100644 --- a/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js +++ b/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js @@ -17,3 +17,21 @@ angular.module('metadatamanagementApp') }); }]); + /** + * Method to request the endpoint that downloads all variables as a PID-formatted json file. + * The response is a list (List) of variable metadata. + * We could not put this into the "VariableResource"-schema (above), because the URLs would not match. + */ + angular.module('metadatamanagementApp').factory('ExportAllVariablesResource', ['$http', + function($http) { + return { + exportAll: function() { + return $http.post('/api/variables/exportAll').then(function(response) { + return response.data; + var blob = new Blob([ response.data ], { type : 'application/json' }); + return blob; //{ blob: response.data, filename: "filename.json" }; + }); + } + } + }]); + From 550817cde7f791c8ecb1b62f9e5dbbb790fc5cf1 Mon Sep 17 00:00:00 2001 From: theresa Date: Wed, 31 Jul 2024 11:53:46 +0200 Subject: [PATCH 05/33] #3303 implemented data collection for PID metadata compilation --- .../ExportAllVariablesResourceController.java | 2 - .../service/VariableManagementService.java | 133 +++++++++++++++++- 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java index 294423242fb..ad186805094 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java @@ -1,11 +1,9 @@ package eu.dzhw.fdz.metadatamanagement.variablemanagement.rest; import java.io.IOException; -import java.rmi.server.ExportException; import javax.persistence.PersistenceException; -import eu.dzhw.fdz.metadatamanagement.projectmanagement.service.DataAcquisitionProjectManagementService; import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.VariableManagementService; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index 8972a92fc7f..a413f1cc302 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -6,6 +6,10 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.rmi.server.ExportException; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -22,17 +26,28 @@ import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Service; +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.ObjectNode; +import com.google.gson.Gson; +import eu.dzhw.fdz.metadatamanagement.common.domain.projections.IdAndVersionProjection; import eu.dzhw.fdz.metadatamanagement.common.service.CrudService; import eu.dzhw.fdz.metadatamanagement.conceptmanagement.domain.Concept; import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.DataPackage; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.repository.DataPackageRepository; import eu.dzhw.fdz.metadatamanagement.datasetmanagement.domain.DataSet; import eu.dzhw.fdz.metadatamanagement.instrumentmanagement.domain.Instrument; import eu.dzhw.fdz.metadatamanagement.projectmanagement.domain.DataAcquisitionProject; +import eu.dzhw.fdz.metadatamanagement.projectmanagement.domain.Release; +import eu.dzhw.fdz.metadatamanagement.projectmanagement.repository.DataAcquisitionProjectRepository; import eu.dzhw.fdz.metadatamanagement.questionmanagement.domain.Question; import eu.dzhw.fdz.metadatamanagement.questionmanagement.repository.QuestionRepository; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.dao.exception.ElasticsearchIoException; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.DataAcquisitionProjectSearchDocument; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.DataPackageSearchDocument; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.DataPackageSubDocument; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.VariableSearchDocument; import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchType; import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchUpdateQueueService; import eu.dzhw.fdz.metadatamanagement.surveymanagement.domain.Survey; @@ -41,6 +56,21 @@ import eu.dzhw.fdz.metadatamanagement.variablemanagement.repository.VariableRepository; import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.helper.VariableCrudHelper; import lombok.RequiredArgsConstructor; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.client.core.CountRequest; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.ExistsQueryBuilder; +import org.elasticsearch.index.query.MatchQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.index.query.TermQueryBuilder; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.SearchHits; +import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.objectweb.asm.TypeReference; /** * Service for managing the domain object/aggregate {@link Variable}. @@ -58,8 +88,15 @@ public class VariableManagementService implements CrudService { private final VariableRepository variableRepository; + private final DataAcquisitionProjectRepository dataAcquisitionProjectRepository; + private final DataPackageRepository dataPackageRepository; + private final VariableCrudHelper crudHelper; + private final ObjectMapper objectMapper = new ObjectMapper(); + private final RestHighLevelClient client; + private final Gson gson; + /** * Delete all variables when the dataAcquisitionProject was deleted. * @@ -222,8 +259,7 @@ public Optional readSearchDocument(String id) { * @throws IOException */ public ResponseEntity exportVariablesAsJSON() throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode jsonNode = objectMapper.createArrayNode(); + ArrayNode jsonNode = this.getPidVariablesMetadata(); File tempFile = new File("tempfile.json"); tempFile.deleteOnExit(); objectMapper.writeValue(tempFile, jsonNode); @@ -239,4 +275,97 @@ public ResponseEntity exportVariablesAsJSON() throws IOException { return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); } } + + /** + * Mapping variable metadata to metadata schema needed for PID registration + * @return + */ + private ArrayNode getPidVariablesMetadata() { + ArrayNode jsonNode = objectMapper.createArrayNode(); + // 1. ES-Query alle DatAaAcquisitionProjects shadow=false, release != null, isPreRelease == false + SearchRequest projectsRequest = new SearchRequest(); + SearchSourceBuilder builderProjects = new SearchSourceBuilder(); + builderProjects.query(QueryBuilders.boolQuery() + .must(new TermQueryBuilder("shadow", true)) + .must(new ExistsQueryBuilder("release")) + .must(new TermQueryBuilder("release.isPreRelease", false))) + .size(10000); + projectsRequest.source(builderProjects); + projectsRequest.indices("data_acquisition_projects"); + try { + SearchResponse response = client.search(projectsRequest, RequestOptions.DEFAULT); + List hits = Arrays.asList(response.getHits().getHits()); + for (var hit : hits) { + DataAcquisitionProjectSearchDocument project = gson.fromJson(hit.getSourceAsString(), DataAcquisitionProjectSearchDocument.class); + // für jedes Ergebnis: 2. ES-Query DataPackages shadow.=true, dataAcquisitionProjectId=project.id-project.version + SearchRequest dataPackagesRequest = new SearchRequest(); + SearchSourceBuilder builderDataPackages = new SearchSourceBuilder(); + builderDataPackages.query(QueryBuilders.boolQuery() + .must(new TermQueryBuilder("shadow", true)) + .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId()))) + .size(10000); + dataPackagesRequest.source(builderDataPackages); + dataPackagesRequest.indices("data_packages"); + SearchResponse responseDataPackage = client.search(dataPackagesRequest, RequestOptions.DEFAULT); + List hitsDataPackages = Arrays.asList(responseDataPackage.getHits().getHits()); + assert hitsDataPackages.size() == 1; + + // 3. ES-Query Variables shadow=true, dataAcquisitionProjectId=project.id-project.version + SearchRequest variablesRequest = new SearchRequest(); + SearchSourceBuilder builderVariables = new SearchSourceBuilder(); + builderVariables.query(QueryBuilders.boolQuery() + .must(new TermQueryBuilder("shadow", true)) + .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId()))) + .size(10000); + variablesRequest.source(builderVariables); + variablesRequest.indices("variables"); + SearchResponse responseVariables = client.search(variablesRequest, RequestOptions.DEFAULT); + List hitsVariables = Arrays.asList(responseVariables.getHits().getHits()); + for (var variable : hitsVariables) { + VariableSearchDocument variableObj = gson.fromJson(variable.getSourceAsString(), VariableSearchDocument.class); + DataPackageSearchDocument dataPackage = gson.fromJson(hitsDataPackages.get(0).getSourceAsString(), DataPackageSearchDocument.class); + ObjectNode obj = this.getPidMetadataOfVariable(variableObj, project, dataPackage); + jsonNode.add(obj); + System.out.println("Adding variable to json " + variableObj.getId()); + } + } + return jsonNode; + } catch (IOException e) { + throw new ElasticsearchIoException(e); + } + } + + /** + * Collects PID metadata of variable + * @param variable the variable metadata is collected for + * @param project the project this variable belongs to + * @param dataPackage the data package this variable belongs to + * @return the metadata as a json node + */ + private ObjectNode getPidMetadataOfVariable( + VariableSearchDocument variable, + DataAcquisitionProject project, + DataPackageSearchDocument dataPackage) { + ObjectNode variableObj = objectMapper.createObjectNode(); + variableObj.put("studyDOI", dataPackage.getDoi()); + variableObj.put("variableName", variable.getName()); + variableObj.put("variableLabel", variable.getLabel().getEn()); // todo: Deutsch oder Englisch? + variableObj.put("pidProposal", "21.T11998/dzhw:" + project.getId() + "_" + variable.getId() + ":" + project.getRelease().getVersion()); + // todo base URL as Constant, Deutsch oder Englisch? + variableObj.put("landingPage", "https://metadata.fdz.dzhw.eu/en/variables/" + variable.getId().replace("$", "") + "?version=" + project.getRelease().getVersion()); + variableObj.put("resourceType", "variable"); + variableObj.put("title", variable.getName() + ": " + variable.getLabel().getEn()); // todo: Deutsch oder Englisch? + // todo creators zusammenstellen + //variableObj.put("creators", ) + variableObj.put("publisher", "FDZ-DZHW"); + // Create DateTimeFormatter instance with specified format + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + // Format LocalDateTime to String + String formattedDateTime = project.getRelease().getLastDate().format(dateTimeFormatter); + variableObj.put("publicationDate", formattedDateTime); + //todo access ways verarbeiten + String accessWays = variable.getAccessWays().toString(); + variableObj.put("availability", accessWays); + return variableObj; + } } From 7075815714a966007ecc4c4200a1fed94e82aef0 Mon Sep 17 00:00:00 2001 From: theresa Date: Wed, 31 Jul 2024 14:23:52 +0200 Subject: [PATCH 06/33] #3303 implemented metadata compilation for PID registration --- .../service/VariableManagementService.java | 78 ++++++++++++++----- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index a413f1cc302..e0db8cf10fe 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -7,6 +7,7 @@ import java.nio.file.Paths; import java.rmi.server.ExportException; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -31,6 +32,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.Gson; +import eu.dzhw.fdz.metadatamanagement.common.domain.Person; import eu.dzhw.fdz.metadatamanagement.common.domain.projections.IdAndVersionProjection; import eu.dzhw.fdz.metadatamanagement.common.service.CrudService; import eu.dzhw.fdz.metadatamanagement.conceptmanagement.domain.Concept; @@ -52,6 +54,7 @@ import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchUpdateQueueService; import eu.dzhw.fdz.metadatamanagement.surveymanagement.domain.Survey; import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; +import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.AccessWays; import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.Variable; import eu.dzhw.fdz.metadatamanagement.variablemanagement.repository.VariableRepository; import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.helper.VariableCrudHelper; @@ -88,15 +91,19 @@ public class VariableManagementService implements CrudService { private final VariableRepository variableRepository; - private final DataAcquisitionProjectRepository dataAcquisitionProjectRepository; - private final DataPackageRepository dataPackageRepository; - private final VariableCrudHelper crudHelper; private final ObjectMapper objectMapper = new ObjectMapper(); + private final RestHighLevelClient client; + private final Gson gson; + private final String LANDING_PAGE_BASE_URL = "https://metadata.fdz.dzhw.eu/en/variables/"; + private final String PID_PREFIX = "21.T11998/dzhw:"; + + + /** * Delete all variables when the dataAcquisitionProject was deleted. * @@ -259,10 +266,12 @@ public Optional readSearchDocument(String id) { * @throws IOException */ public ResponseEntity exportVariablesAsJSON() throws IOException { - ArrayNode jsonNode = this.getPidVariablesMetadata(); + ArrayNode variableMetadata = this.getPidVariablesMetadata(); + ObjectNode node = objectMapper.createObjectNode(); + node.set("variables", variableMetadata); File tempFile = new File("tempfile.json"); tempFile.deleteOnExit(); - objectMapper.writeValue(tempFile, jsonNode); + objectMapper.writeValue(tempFile, node); Path path = Paths.get(tempFile.getAbsolutePath()); try { ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path)); @@ -289,7 +298,7 @@ private ArrayNode getPidVariablesMetadata() { .must(new TermQueryBuilder("shadow", true)) .must(new ExistsQueryBuilder("release")) .must(new TermQueryBuilder("release.isPreRelease", false))) - .size(10000); + .size(10); projectsRequest.source(builderProjects); projectsRequest.indices("data_acquisition_projects"); try { @@ -303,7 +312,7 @@ private ArrayNode getPidVariablesMetadata() { builderDataPackages.query(QueryBuilders.boolQuery() .must(new TermQueryBuilder("shadow", true)) .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId()))) - .size(10000); + .size(10); dataPackagesRequest.source(builderDataPackages); dataPackagesRequest.indices("data_packages"); SearchResponse responseDataPackage = client.search(dataPackagesRequest, RequestOptions.DEFAULT); @@ -316,7 +325,7 @@ private ArrayNode getPidVariablesMetadata() { builderVariables.query(QueryBuilders.boolQuery() .must(new TermQueryBuilder("shadow", true)) .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId()))) - .size(10000); + .size(10); variablesRequest.source(builderVariables); variablesRequest.indices("variables"); SearchResponse responseVariables = client.search(variablesRequest, RequestOptions.DEFAULT); @@ -350,22 +359,51 @@ private ObjectNode getPidMetadataOfVariable( variableObj.put("studyDOI", dataPackage.getDoi()); variableObj.put("variableName", variable.getName()); variableObj.put("variableLabel", variable.getLabel().getEn()); // todo: Deutsch oder Englisch? - variableObj.put("pidProposal", "21.T11998/dzhw:" + project.getId() + "_" + variable.getId() + ":" + project.getRelease().getVersion()); - // todo base URL as Constant, Deutsch oder Englisch? - variableObj.put("landingPage", "https://metadata.fdz.dzhw.eu/en/variables/" + variable.getId().replace("$", "") + "?version=" + project.getRelease().getVersion()); - variableObj.put("resourceType", "variable"); + variableObj.put("pidProposal", PID_PREFIX + project.getId() + "_" + variable.getName() + ":" + project.getRelease().getVersion()); + // todo: Deutsch oder Englisch? + variableObj.put("landingPage", LANDING_PAGE_BASE_URL + + variable.getMasterId().replace("$", "") + + "?version=" + project.getRelease().getVersion()); + variableObj.put("resourceType", "Variable"); variableObj.put("title", variable.getName() + ": " + variable.getLabel().getEn()); // todo: Deutsch oder Englisch? - // todo creators zusammenstellen - //variableObj.put("creators", ) + variableObj.set("creators", this.compileCreators(dataPackage.getProjectContributors())); variableObj.put("publisher", "FDZ-DZHW"); - // Create DateTimeFormatter instance with specified format - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); - // Format LocalDateTime to String + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String formattedDateTime = project.getRelease().getLastDate().format(dateTimeFormatter); variableObj.put("publicationDate", formattedDateTime); - //todo access ways verarbeiten - String accessWays = variable.getAccessWays().toString(); - variableObj.put("availability", accessWays); + variableObj.put("availability", this.compileAccessWays(variable.getAccessWays())); return variableObj; } + + /** + * Compiles the given list of project contributor entries into a PID metadata list. + * @param projectContributors the list of contributors of this project + * @return a list of contributors as needed for PID registration + */ + private ArrayNode compileCreators(List projectContributors) { + ArrayNode contributorList = objectMapper.createArrayNode(); + for (var person : projectContributors) { + ObjectNode p = objectMapper.createObjectNode(); + p.put("firstName", person.getFirstName()); + if (person.getMiddleName() != null && !person.getMiddleName().isEmpty()) { + p.put("middleName", person.getMiddleName()); + } + p.put("lastName", person.getLastName()); + contributorList.add(p); + } + return contributorList; + } + + /** + * Compiles the given list of accessway entries into a readable string. + * @param accessWays list of access ways + * @return a readable string of access ways + */ + private String compileAccessWays(List accessWays) { + List strList = new ArrayList<>(); + for (var access : accessWays) { + strList.add(AccessWays.displayAccessWay(access)); + } + return String.join(", ", strList); + } } From 37a76899af32ac11dc767ea98ed0c4bcb889dc0c Mon Sep 17 00:00:00 2001 From: theresa Date: Fri, 2 Aug 2024 10:55:58 +0200 Subject: [PATCH 07/33] #3303: improved queries --- .../service/VariableManagementService.java | 68 ++++++++++++++++--- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index e0db8cf10fe..75c8a34409f 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -59,6 +59,7 @@ import eu.dzhw.fdz.metadatamanagement.variablemanagement.repository.VariableRepository; import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.helper.VariableCrudHelper; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; @@ -83,6 +84,7 @@ @Service @RepositoryEventHandler @RequiredArgsConstructor +@Slf4j public class VariableManagementService implements CrudService { private final QuestionRepository questionRepository; @@ -277,6 +279,7 @@ public ResponseEntity exportVariablesAsJSON() throws IOException { ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path)); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment; filename=Variables_PID_MDM_Export.json"); + log.info("Finished variable export with " + variableMetadata.size() + " variables."); return ResponseEntity.ok() .headers(headers) .body(resource); @@ -287,7 +290,7 @@ public ResponseEntity exportVariablesAsJSON() throws IOException { /** * Mapping variable metadata to metadata schema needed for PID registration - * @return + * @return collected metadata as JsonNode */ private ArrayNode getPidVariablesMetadata() { ArrayNode jsonNode = objectMapper.createArrayNode(); @@ -295,15 +298,17 @@ private ArrayNode getPidVariablesMetadata() { SearchRequest projectsRequest = new SearchRequest(); SearchSourceBuilder builderProjects = new SearchSourceBuilder(); builderProjects.query(QueryBuilders.boolQuery() - .must(new TermQueryBuilder("shadow", true)) + .must(new TermQueryBuilder("shadow", false)) + .must(new TermQueryBuilder("hidden", false)) .must(new ExistsQueryBuilder("release")) .must(new TermQueryBuilder("release.isPreRelease", false))) - .size(10); + .size(10000); projectsRequest.source(builderProjects); projectsRequest.indices("data_acquisition_projects"); try { SearchResponse response = client.search(projectsRequest, RequestOptions.DEFAULT); List hits = Arrays.asList(response.getHits().getHits()); + log.info("Exporting variables for " + hits.size() + " projects"); for (var hit : hits) { DataAcquisitionProjectSearchDocument project = gson.fromJson(hit.getSourceAsString(), DataAcquisitionProjectSearchDocument.class); // für jedes Ergebnis: 2. ES-Query DataPackages shadow.=true, dataAcquisitionProjectId=project.id-project.version @@ -311,7 +316,7 @@ private ArrayNode getPidVariablesMetadata() { SearchSourceBuilder builderDataPackages = new SearchSourceBuilder(); builderDataPackages.query(QueryBuilders.boolQuery() .must(new TermQueryBuilder("shadow", true)) - .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId()))) + .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId() + "-" + project.getRelease().getVersion()))) .size(10); dataPackagesRequest.source(builderDataPackages); dataPackagesRequest.indices("data_packages"); @@ -324,8 +329,8 @@ private ArrayNode getPidVariablesMetadata() { SearchSourceBuilder builderVariables = new SearchSourceBuilder(); builderVariables.query(QueryBuilders.boolQuery() .must(new TermQueryBuilder("shadow", true)) - .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId()))) - .size(10); + .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId() + "-" + project.getRelease().getVersion()))) + .size(10000); variablesRequest.source(builderVariables); variablesRequest.indices("variables"); SearchResponse responseVariables = client.search(variablesRequest, RequestOptions.DEFAULT); @@ -334,8 +339,9 @@ private ArrayNode getPidVariablesMetadata() { VariableSearchDocument variableObj = gson.fromJson(variable.getSourceAsString(), VariableSearchDocument.class); DataPackageSearchDocument dataPackage = gson.fromJson(hitsDataPackages.get(0).getSourceAsString(), DataPackageSearchDocument.class); ObjectNode obj = this.getPidMetadataOfVariable(variableObj, project, dataPackage); - jsonNode.add(obj); - System.out.println("Adding variable to json " + variableObj.getId()); + if (obj != null) { + jsonNode.add(obj); + } } } return jsonNode; @@ -345,7 +351,7 @@ private ArrayNode getPidVariablesMetadata() { } /** - * Collects PID metadata of variable + * Collects PID metadata of a variable * @param variable the variable metadata is collected for * @param project the project this variable belongs to * @param dataPackage the data package this variable belongs to @@ -355,10 +361,13 @@ private ObjectNode getPidMetadataOfVariable( VariableSearchDocument variable, DataAcquisitionProject project, DataPackageSearchDocument dataPackage) { + if (this.hasMissingFields(variable, project, dataPackage)) { + return null; + } ObjectNode variableObj = objectMapper.createObjectNode(); variableObj.put("studyDOI", dataPackage.getDoi()); variableObj.put("variableName", variable.getName()); - variableObj.put("variableLabel", variable.getLabel().getEn()); // todo: Deutsch oder Englisch? + variableObj.put("variableLabel", variable.getLabel().getEn() != null ? variable.getLabel().getEn() : variable.getLabel().getDe()); // todo: Deutsch oder Englisch? variableObj.put("pidProposal", PID_PREFIX + project.getId() + "_" + variable.getName() + ":" + project.getRelease().getVersion()); // todo: Deutsch oder Englisch? variableObj.put("landingPage", LANDING_PAGE_BASE_URL @@ -375,6 +384,45 @@ private ObjectNode getPidMetadataOfVariable( return variableObj; } + /** + * Checks the required fields for PID registration. Variables with missing required fields will not be exported. + * @param variable the variable for which a PID should be registered + * @param project the project this variable belongs to + * @param dataPackage the data package this variable belongs to + * @return true if required fields are missing, else false + */ + private boolean hasMissingFields(VariableSearchDocument variable, DataAcquisitionProject project, DataPackageSearchDocument dataPackage) { + if (variable.getName() == null || variable.getName().isEmpty()) { + log.info(String.format("Unable to export variable with id '%s'. Required variable name is missing.", variable.getId())); + return true; + } + if (variable.getLabel() == null) { + log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", variable.getId())); + return true; + } else if ((variable.getLabel().getDe() == null || variable.getLabel().getDe().trim().isEmpty()) + && (variable.getLabel().getEn() == null || variable.getLabel().getEn().trim().isEmpty())) { + log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", variable.getId())); + return true; + } + if (dataPackage.getDoi() == null || dataPackage.getDoi().trim().isEmpty()) { + log.info(String.format("Unable to export variable with id '%s'. Required datapackage DOIl is missing.", variable.getId())); + return true; + } + if (dataPackage.getProjectContributors() == null || dataPackage.getProjectContributors().isEmpty()) { + log.info(String.format("Unable to export variable with id '%s'. Datapackage has no contributors.", variable.getId())); + return true; + } + if (project.getId() == null + || project.getRelease() == null + || project.getRelease().getVersion() == null + || project.getRelease().getVersion().trim().isEmpty() + || project.getRelease().getLastDate() == null){ + log.info(String.format("Unable to export variable with id '%s'. Required project fields are missing.", variable.getId())); + return true; + } + return false; + } + /** * Compiles the given list of project contributor entries into a PID metadata list. * @param projectContributors the list of contributors of this project From 4fac024350085ecb9e2f96520f4fdacdffb58a44 Mon Sep 17 00:00:00 2001 From: theresa Date: Fri, 2 Aug 2024 13:03:45 +0200 Subject: [PATCH 08/33] #3303 fixed code style --- .../variablemanagement/domain/Variable.java | 4 +- .../ExportAllVariablesResourceController.java | 5 +- .../service/VariableManagementService.java | 92 +++++++++++-------- 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java index 7e63b8411ee..5330a8f51a2 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/Variable.java @@ -143,8 +143,8 @@ public class Variable extends AbstractShadowableRdcDomainObject { */ @Size(max = StringLengths.MEDIUM, message = "variable-management.error.pid.size") @Pattern( - message = "variable-management.error.pid.pattern", - regexp = Patterns.PID) + message = "variable-management.error.pid.pattern", + regexp = Patterns.PID) private String pid; /** diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java index ad186805094..625360fd99c 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportAllVariablesResourceController.java @@ -17,6 +17,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +/** + * Controller for exporting all variables for PID registration. + */ @Controller @RequestMapping("/api") @RequiredArgsConstructor @@ -35,7 +38,7 @@ public class ExportAllVariablesResourceController { public ResponseEntity exportAllVariables() { ResponseEntity response = new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); try { - response = this.variablesManagementService.exportVariablesAsJSON(); + response = this.variablesManagementService.exportVariablesAsJson(); } catch (PersistenceException | IOException ex) { return response; } diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index 75c8a34409f..687e1870642 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -101,8 +101,8 @@ public class VariableManagementService implements CrudService { private final Gson gson; - private final String LANDING_PAGE_BASE_URL = "https://metadata.fdz.dzhw.eu/en/variables/"; - private final String PID_PREFIX = "21.T11998/dzhw:"; + private final String landingPageBaseUrl = "https://metadata.fdz.dzhw.eu/en/variables/"; + private final String pidPrefix = "21.T11998/dzhw:"; @@ -265,9 +265,9 @@ public Optional readSearchDocument(String id) { /** * Writes all variable data according to the PID metadata schema to a JSON file. * @return the JSON file - * @throws IOException + * @throws IOException if elasticsearch fails */ - public ResponseEntity exportVariablesAsJSON() throws IOException { + public ResponseEntity exportVariablesAsJson() throws IOException { ArrayNode variableMetadata = this.getPidVariablesMetadata(); ObjectNode node = objectMapper.createObjectNode(); node.set("variables", variableMetadata); @@ -289,12 +289,11 @@ public ResponseEntity exportVariablesAsJSON() throws IOException { } /** - * Mapping variable metadata to metadata schema needed for PID registration + * Mapping variable metadata to metadata schema needed for PID registration. * @return collected metadata as JsonNode */ private ArrayNode getPidVariablesMetadata() { ArrayNode jsonNode = objectMapper.createArrayNode(); - // 1. ES-Query alle DatAaAcquisitionProjects shadow=false, release != null, isPreRelease == false SearchRequest projectsRequest = new SearchRequest(); SearchSourceBuilder builderProjects = new SearchSourceBuilder(); builderProjects.query(QueryBuilders.boolQuery() @@ -310,13 +309,14 @@ private ArrayNode getPidVariablesMetadata() { List hits = Arrays.asList(response.getHits().getHits()); log.info("Exporting variables for " + hits.size() + " projects"); for (var hit : hits) { - DataAcquisitionProjectSearchDocument project = gson.fromJson(hit.getSourceAsString(), DataAcquisitionProjectSearchDocument.class); - // für jedes Ergebnis: 2. ES-Query DataPackages shadow.=true, dataAcquisitionProjectId=project.id-project.version + DataAcquisitionProjectSearchDocument project = gson.fromJson( + hit.getSourceAsString(), DataAcquisitionProjectSearchDocument.class); SearchRequest dataPackagesRequest = new SearchRequest(); SearchSourceBuilder builderDataPackages = new SearchSourceBuilder(); builderDataPackages.query(QueryBuilders.boolQuery() .must(new TermQueryBuilder("shadow", true)) - .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId() + "-" + project.getRelease().getVersion()))) + .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId() + + "-" + project.getRelease().getVersion()))) .size(10); dataPackagesRequest.source(builderDataPackages); dataPackagesRequest.indices("data_packages"); @@ -329,15 +329,18 @@ private ArrayNode getPidVariablesMetadata() { SearchSourceBuilder builderVariables = new SearchSourceBuilder(); builderVariables.query(QueryBuilders.boolQuery() .must(new TermQueryBuilder("shadow", true)) - .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId() + "-" + project.getRelease().getVersion()))) + .must(new TermQueryBuilder("dataAcquisitionProjectId", project.getId() + + "-" + project.getRelease().getVersion()))) .size(10000); variablesRequest.source(builderVariables); variablesRequest.indices("variables"); SearchResponse responseVariables = client.search(variablesRequest, RequestOptions.DEFAULT); List hitsVariables = Arrays.asList(responseVariables.getHits().getHits()); for (var variable : hitsVariables) { - VariableSearchDocument variableObj = gson.fromJson(variable.getSourceAsString(), VariableSearchDocument.class); - DataPackageSearchDocument dataPackage = gson.fromJson(hitsDataPackages.get(0).getSourceAsString(), DataPackageSearchDocument.class); + VariableSearchDocument variableObj = gson.fromJson( + variable.getSourceAsString(), VariableSearchDocument.class); + DataPackageSearchDocument dataPackage = gson.fromJson( + hitsDataPackages.get(0).getSourceAsString(), DataPackageSearchDocument.class); ObjectNode obj = this.getPidMetadataOfVariable(variableObj, project, dataPackage); if (obj != null) { jsonNode.add(obj); @@ -351,30 +354,35 @@ private ArrayNode getPidVariablesMetadata() { } /** - * Collects PID metadata of a variable + * Collects PID metadata of a variable. * @param variable the variable metadata is collected for * @param project the project this variable belongs to * @param dataPackage the data package this variable belongs to * @return the metadata as a json node */ private ObjectNode getPidMetadataOfVariable( - VariableSearchDocument variable, - DataAcquisitionProject project, - DataPackageSearchDocument dataPackage) { + VariableSearchDocument variable, + DataAcquisitionProject project, + DataPackageSearchDocument dataPackage) { if (this.hasMissingFields(variable, project, dataPackage)) { return null; } ObjectNode variableObj = objectMapper.createObjectNode(); variableObj.put("studyDOI", dataPackage.getDoi()); variableObj.put("variableName", variable.getName()); - variableObj.put("variableLabel", variable.getLabel().getEn() != null ? variable.getLabel().getEn() : variable.getLabel().getDe()); // todo: Deutsch oder Englisch? - variableObj.put("pidProposal", PID_PREFIX + project.getId() + "_" + variable.getName() + ":" + project.getRelease().getVersion()); - // todo: Deutsch oder Englisch? - variableObj.put("landingPage", LANDING_PAGE_BASE_URL - + variable.getMasterId().replace("$", "") - + "?version=" + project.getRelease().getVersion()); + // todo: Clarify which language to use + variableObj.put("variableLabel", variable.getLabel().getEn() != null ? + variable.getLabel().getEn() : + variable.getLabel().getDe()); + variableObj.put("pidProposal", pidPrefix + project.getId() + "_" + variable.getName() + ":" + + project.getRelease().getVersion()); + // todo: Clarify which language to use + variableObj.put("landingPage", landingPageBaseUrl + + variable.getMasterId().replace("$", "") + + "?version=" + project.getRelease().getVersion()); variableObj.put("resourceType", "Variable"); - variableObj.put("title", variable.getName() + ": " + variable.getLabel().getEn()); // todo: Deutsch oder Englisch? + // todo: Clarify which language to use + variableObj.put("title", variable.getName() + ": " + variable.getLabel().getEn()); variableObj.set("creators", this.compileCreators(dataPackage.getProjectContributors())); variableObj.put("publisher", "FDZ-DZHW"); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @@ -393,31 +401,37 @@ private ObjectNode getPidMetadataOfVariable( */ private boolean hasMissingFields(VariableSearchDocument variable, DataAcquisitionProject project, DataPackageSearchDocument dataPackage) { if (variable.getName() == null || variable.getName().isEmpty()) { - log.info(String.format("Unable to export variable with id '%s'. Required variable name is missing.", variable.getId())); + log.info(String.format("Unable to export variable with id '%s'. Required variable name is missing.", + variable.getId())); return true; } if (variable.getLabel() == null) { - log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", variable.getId())); + log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", + variable.getId())); return true; } else if ((variable.getLabel().getDe() == null || variable.getLabel().getDe().trim().isEmpty()) - && (variable.getLabel().getEn() == null || variable.getLabel().getEn().trim().isEmpty())) { - log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", variable.getId())); + && (variable.getLabel().getEn() == null || variable.getLabel().getEn().trim().isEmpty())) { + log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", + variable.getId())); return true; } if (dataPackage.getDoi() == null || dataPackage.getDoi().trim().isEmpty()) { - log.info(String.format("Unable to export variable with id '%s'. Required datapackage DOIl is missing.", variable.getId())); + log.info(String.format("Unable to export variable with id '%s'. Required datapackage DOIl is missing.", + variable.getId())); return true; } if (dataPackage.getProjectContributors() == null || dataPackage.getProjectContributors().isEmpty()) { - log.info(String.format("Unable to export variable with id '%s'. Datapackage has no contributors.", variable.getId())); + log.info(String.format("Unable to export variable with id '%s'. Datapackage has no contributors.", + variable.getId())); return true; } if (project.getId() == null - || project.getRelease() == null - || project.getRelease().getVersion() == null - || project.getRelease().getVersion().trim().isEmpty() - || project.getRelease().getLastDate() == null){ - log.info(String.format("Unable to export variable with id '%s'. Required project fields are missing.", variable.getId())); + || project.getRelease() == null + || project.getRelease().getVersion() == null + || project.getRelease().getVersion().trim().isEmpty() + || project.getRelease().getLastDate() == null) { + log.info(String.format("Unable to export variable with id '%s'. Required project fields are missing.", + variable.getId())); return true; } return false; @@ -431,13 +445,13 @@ private boolean hasMissingFields(VariableSearchDocument variable, DataAcquisitio private ArrayNode compileCreators(List projectContributors) { ArrayNode contributorList = objectMapper.createArrayNode(); for (var person : projectContributors) { - ObjectNode p = objectMapper.createObjectNode(); - p.put("firstName", person.getFirstName()); + ObjectNode personNode = objectMapper.createObjectNode(); + personNode.put("firstName", person.getFirstName()); if (person.getMiddleName() != null && !person.getMiddleName().isEmpty()) { - p.put("middleName", person.getMiddleName()); + personNode.put("middleName", person.getMiddleName()); } - p.put("lastName", person.getLastName()); - contributorList.add(p); + personNode.put("lastName", person.getLastName()); + contributorList.add(personNode); } return contributorList; } From 09fa0af47c57b4555484e816d18c9725b59df2ec Mon Sep 17 00:00:00 2001 From: theresa Date: Fri, 2 Aug 2024 13:08:28 +0200 Subject: [PATCH 09/33] #3303 code style fix again --- .../service/VariableManagementService.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index 687e1870642..0f671645ea1 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -310,7 +310,7 @@ private ArrayNode getPidVariablesMetadata() { log.info("Exporting variables for " + hits.size() + " projects"); for (var hit : hits) { DataAcquisitionProjectSearchDocument project = gson.fromJson( - hit.getSourceAsString(), DataAcquisitionProjectSearchDocument.class); + hit.getSourceAsString(), DataAcquisitionProjectSearchDocument.class); SearchRequest dataPackagesRequest = new SearchRequest(); SearchSourceBuilder builderDataPackages = new SearchSourceBuilder(); builderDataPackages.query(QueryBuilders.boolQuery() @@ -338,9 +338,9 @@ private ArrayNode getPidVariablesMetadata() { List hitsVariables = Arrays.asList(responseVariables.getHits().getHits()); for (var variable : hitsVariables) { VariableSearchDocument variableObj = gson.fromJson( - variable.getSourceAsString(), VariableSearchDocument.class); + variable.getSourceAsString(), VariableSearchDocument.class); DataPackageSearchDocument dataPackage = gson.fromJson( - hitsDataPackages.get(0).getSourceAsString(), DataPackageSearchDocument.class); + hitsDataPackages.get(0).getSourceAsString(), DataPackageSearchDocument.class); ObjectNode obj = this.getPidMetadataOfVariable(variableObj, project, dataPackage); if (obj != null) { jsonNode.add(obj); @@ -371,9 +371,9 @@ private ObjectNode getPidMetadataOfVariable( variableObj.put("studyDOI", dataPackage.getDoi()); variableObj.put("variableName", variable.getName()); // todo: Clarify which language to use - variableObj.put("variableLabel", variable.getLabel().getEn() != null ? - variable.getLabel().getEn() : - variable.getLabel().getDe()); + variableObj.put("variableLabel", variable.getLabel().getEn() != null + ? variable.getLabel().getEn() : + variable.getLabel().getDe()); variableObj.put("pidProposal", pidPrefix + project.getId() + "_" + variable.getName() + ":" + project.getRelease().getVersion()); // todo: Clarify which language to use @@ -399,30 +399,32 @@ private ObjectNode getPidMetadataOfVariable( * @param dataPackage the data package this variable belongs to * @return true if required fields are missing, else false */ - private boolean hasMissingFields(VariableSearchDocument variable, DataAcquisitionProject project, DataPackageSearchDocument dataPackage) { + private boolean hasMissingFields(VariableSearchDocument variable, + DataAcquisitionProject project, + DataPackageSearchDocument dataPackage) { if (variable.getName() == null || variable.getName().isEmpty()) { log.info(String.format("Unable to export variable with id '%s'. Required variable name is missing.", - variable.getId())); + variable.getId())); return true; } if (variable.getLabel() == null) { log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", - variable.getId())); + variable.getId())); return true; } else if ((variable.getLabel().getDe() == null || variable.getLabel().getDe().trim().isEmpty()) && (variable.getLabel().getEn() == null || variable.getLabel().getEn().trim().isEmpty())) { log.info(String.format("Unable to export variable with id '%s'. Required variable label is missing.", - variable.getId())); + variable.getId())); return true; } if (dataPackage.getDoi() == null || dataPackage.getDoi().trim().isEmpty()) { log.info(String.format("Unable to export variable with id '%s'. Required datapackage DOIl is missing.", - variable.getId())); + variable.getId())); return true; } if (dataPackage.getProjectContributors() == null || dataPackage.getProjectContributors().isEmpty()) { log.info(String.format("Unable to export variable with id '%s'. Datapackage has no contributors.", - variable.getId())); + variable.getId())); return true; } if (project.getId() == null @@ -431,7 +433,7 @@ private boolean hasMissingFields(VariableSearchDocument variable, DataAcquisitio || project.getRelease().getVersion().trim().isEmpty() || project.getRelease().getLastDate() == null) { log.info(String.format("Unable to export variable with id '%s'. Required project fields are missing.", - variable.getId())); + variable.getId())); return true; } return false; From 2079bbfde0949073185bcfec3ecf1147285bb004 Mon Sep 17 00:00:00 2001 From: theresa Date: Mon, 5 Aug 2024 13:31:10 +0200 Subject: [PATCH 10/33] #3303 optimized variable export without temp file --- .../service/VariableManagementService.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index 0f671645ea1..6803868b7ff 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -271,12 +271,8 @@ public ResponseEntity exportVariablesAsJson() throws IOException { ArrayNode variableMetadata = this.getPidVariablesMetadata(); ObjectNode node = objectMapper.createObjectNode(); node.set("variables", variableMetadata); - File tempFile = new File("tempfile.json"); - tempFile.deleteOnExit(); - objectMapper.writeValue(tempFile, node); - Path path = Paths.get(tempFile.getAbsolutePath()); try { - ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path)); + ByteArrayResource resource = new ByteArrayResource(objectMapper.writeValueAsBytes(node)); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment; filename=Variables_PID_MDM_Export.json"); log.info("Finished variable export with " + variableMetadata.size() + " variables."); From 287f633539a69dd5a0cc114cb2072b15535830b1 Mon Sep 17 00:00:00 2001 From: theresa Date: Wed, 7 Aug 2024 10:20:41 +0200 Subject: [PATCH 11/33] #3304 prepared endpoint for DDI codebook export of study variables --- .../views/survey-detail.controller.js | 23 +++++++- .../views/survey-detail.html.tmpl | 8 +++ .../resources/variable.resource.js | 15 +++++ pom.xml | 4 ++ .../variablemanagement/domain/CodeBook.java | 8 +++ .../ExportDdiVariablesResourceController.java | 51 ++++++++++++++++ .../service/VariableManagementService.java | 59 +++++++++++++++---- 7 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java diff --git a/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js b/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js index ef66dc214c1..41e92391d88 100644 --- a/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js +++ b/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js @@ -24,6 +24,7 @@ angular.module('metadatamanagementApp') '$stateParams', 'blockUI', '$mdSidenav', + 'ExportDdiVariablesResource', function(entity, LanguageService, CleanJSObjectService, PageMetadataService, $state, BreadcrumbService, MessageBus, SurveySearchService, SurveyAttachmentResource, Principal, @@ -31,7 +32,7 @@ angular.module('metadatamanagementApp') SurveyResponseRateImageUploadService, OutdatedVersionNotifier, DataAcquisitionProjectResource, $mdDialog, ProjectUpdateAccessService, CountryCodesResource, $stateParams, - blockUI, $mdSidenav) { + blockUI, $mdSidenav, ExportDdiVariablesResource) { blockUI.start(); SearchResultNavigatorService .setSearchIndex($stateParams['search-result-index']); @@ -53,6 +54,8 @@ angular.module('metadatamanagementApp') ctrl.responseRateImage = null; ctrl.enableJsonView = Principal .hasAnyAuthority(['ROLE_PUBLISHER', 'ROLE_ADMIN']); + ctrl.enableVariableExport = Principal + .hasAnyAuthority(['ROLE_PUBLISHER', 'ROLE_ADMIN']); entity.promise.then(function(survey) { var fetchFn = SurveySearchService.findShadowByIdAndVersion @@ -174,5 +177,23 @@ angular.module('metadatamanagementApp') ctrl.toggleSidenav = function() { $mdSidenav('SideNavBar').toggle(); }; + + /** + * Exports Variables metadata as DDI Codebook XML. + */ + ctrl.exportVariables = function() { + ExportDdiVariablesResource.exportVariablesAsXml({ + studyId: "foo" + }).then(function(res) { + var blob = new Blob([res],{ + type: "application/xml;charset=utf-8;" + }); + var downloadLink = document.createElement('a'); + downloadLink.setAttribute('download', 'variable_ddi_mdm_export.xml'); + downloadLink.setAttribute('href', window.URL.createObjectURL(blob)); + downloadLink.click(); + $scope.isDownloadingData = false; + }) + } }]); diff --git a/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.html.tmpl b/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.html.tmpl index bbae6877755..896dc20adc3 100644 --- a/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.html.tmpl +++ b/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.html.tmpl @@ -10,6 +10,14 @@

+ + + Daten als XML exportieren + + DDI + diff --git a/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js b/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js index cb060358881..9704ceea70c 100644 --- a/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js +++ b/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js @@ -17,3 +17,18 @@ angular.module('metadatamanagementApp') }); }]); + /** + * Method to request the endpoint that downloads all variables of the study as a DDI-formatted XML file. + * We could not put this into the "VariableResource"-schema (above), because the URLs would not match. + */ + angular.module('metadatamanagementApp').factory('ExportDdiVariablesResource', ['$http', + function($http) { + return { + exportVariablesAsXml: function() { + return $http.get('api/variables/exportDDI/xml/:studyId').then(function(response) { + return response.data; + }); + } + } + }]); + diff --git a/pom.xml b/pom.xml index 7632a09471b..32a6413cbc2 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,10 @@ com.fasterxml.jackson.core jackson-databind + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + com.github.cloudyrock.mongock mongock-spring-v5 diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java new file mode 100644 index 00000000000..458c10b8efd --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java @@ -0,0 +1,8 @@ +package eu.dzhw.fdz.metadatamanagement.variablemanagement.domain; + +public record CodeBook(String name, String address) { + public CodeBook(String name, String address) { + this.name = name; + this.address = address; + } +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java new file mode 100644 index 00000000000..3adf8f5bb5e --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java @@ -0,0 +1,51 @@ +package eu.dzhw.fdz.metadatamanagement.variablemanagement.rest; + +import java.io.IOException; + +import javax.persistence.PersistenceException; + +import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; +import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.VariableManagementService; +import lombok.RequiredArgsConstructor; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * Controller for exporting variable metadata as DDI codebook. + */ +@Controller +@RequestMapping("/api") +@RequiredArgsConstructor +public class ExportDdiVariablesResourceController { + + private final VariableManagementService variablesManagementService; + + /** + * Exports all variables metadata belonging to the given survey ID as DDI Codebook. + * + * @return an XML file + */ + @GetMapping(value = "/variables/exportDDI/xml/{studyId:.+}", produces = MediaType.APPLICATION_XML_VALUE) + @ResponseBody + @Secured(value = {AuthoritiesConstants.PUBLISHER, AuthoritiesConstants.DATA_PROVIDER}) + public ResponseEntity exportVariablesAsXml(@PathVariable String studyId) { + ResponseEntity response = new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); + try { + response = this.variablesManagementService.exportDdiVariablesAsXML(studyId); + } catch (PersistenceException ex) { + return response; + } + + return response; + } + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index ad331fbf77a..0829d50bcb3 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -1,17 +1,25 @@ package eu.dzhw.fdz.metadatamanagement.variablemanagement.service; +import java.io.IOException; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.springframework.core.io.ByteArrayResource; import org.springframework.data.rest.core.annotation.HandleAfterCreate; import org.springframework.data.rest.core.annotation.HandleAfterDelete; import org.springframework.data.rest.core.annotation.HandleAfterSave; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; import eu.dzhw.fdz.metadatamanagement.common.service.CrudService; import eu.dzhw.fdz.metadatamanagement.conceptmanagement.domain.Concept; import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.DataPackage; @@ -24,19 +32,22 @@ import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchUpdateQueueService; import eu.dzhw.fdz.metadatamanagement.surveymanagement.domain.Survey; import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; +import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.CodeBook; import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.Variable; import eu.dzhw.fdz.metadatamanagement.variablemanagement.repository.VariableRepository; import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.helper.VariableCrudHelper; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; /** * Service for managing the domain object/aggregate {@link Variable}. - * + * * @author René Reitmann */ @Service @RepositoryEventHandler @RequiredArgsConstructor +@Slf4j public class VariableManagementService implements CrudService { private final QuestionRepository questionRepository; @@ -49,7 +60,7 @@ public class VariableManagementService implements CrudService { /** * Delete all variables when the dataAcquisitionProject was deleted. - * + * * @param dataAcquisitionProject the dataAcquisitionProject which has been deleted. */ @HandleAfterDelete @@ -59,7 +70,7 @@ public void onDataAcquisitionProjectDeleted(DataAcquisitionProject dataAcquisiti /** * Update all variables of the project, when the project is released. - * + * * @param dataAcquisitionProject the changed project */ @HandleAfterSave @@ -72,7 +83,7 @@ public void onDataAcquisitionProjectUpdated(DataAcquisitionProject dataAcquisiti /** * A service method for deletion of variables within a data acquisition project. - * + * * @param dataAcquisitionProjectId the id for to the data acquisition project. */ @Secured(value = {AuthoritiesConstants.PUBLISHER, AuthoritiesConstants.DATA_PROVIDER}) @@ -88,7 +99,7 @@ public void deleteAllVariablesByProjectId(String dataAcquisitionProjectId) { /** * Enqueue update of variable search documents when the data set is changed. - * + * * @param dataSet the updated, created or deleted data set. */ @HandleAfterCreate @@ -102,7 +113,7 @@ public void onDataSetChanged(DataSet dataSet) { /** * Enqueue update of variable search documents when the dataPackage is changed. - * + * * @param dataPackage the updated, created or deleted dataPackage. */ @HandleAfterCreate @@ -116,7 +127,7 @@ public void onDataPackageChanged(DataPackage dataPackage) { /** * Enqueue update of variable search documents when the instrument is changed. - * + * * @param instrument the updated, created or deleted instrument. */ @HandleAfterCreate @@ -130,7 +141,7 @@ public void onInstrumentChanged(Instrument instrument) { /** * Enqueue update of variable search documents when the question is changed. - * + * * @param question the updated, created or deleted question. */ @HandleAfterCreate @@ -144,7 +155,7 @@ public void onQuestionChanged(Question question) { /** * Enqueue update of variable search documents when the survey is updated. - * + * * @param survey the updated, created or deleted survey. */ @HandleAfterCreate @@ -158,7 +169,7 @@ public void onSurveyChanged(Survey survey) { /** * Enqueue update of variable search documents when the concept is changed. - * + * * @param concept the updated, created or deleted concept. */ @HandleAfterCreate @@ -202,4 +213,32 @@ public Optional read(String id) { public Optional readSearchDocument(String id) { return crudHelper.readSearchDocument(id); } + + /** + * Exports all variables belonging to a given study according to the DDI Codebook standard. + * @param studyId the ID of the study + * @return DDI metadata as XML + */ + public ResponseEntity exportDdiVariablesAsXML(String studyId) { + try { + CodeBook variableMetadata = this.getDdiVariablesMetadata(); + XmlMapper mapper = new XmlMapper(); + ByteArrayResource resource = new ByteArrayResource(mapper.writeValueAsBytes(variableMetadata)); + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Disposition", "attachment; filename=Variables_PID_MDM_Export.xml"); + return ResponseEntity.ok() + .headers(headers) + .body(resource); + } catch (IOException ex) { + return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); + } + } + + /** + * Collects metadata according to DDI Codebook standard. + * @return the metadata + */ + private CodeBook getDdiVariablesMetadata() throws JsonProcessingException { + return new CodeBook("Foo", "bar"); + } } From 2b3ad054670017750fe22e0d5d5f9d5f1b913f9f Mon Sep 17 00:00:00 2001 From: theresa Date: Fri, 9 Aug 2024 15:14:28 +0200 Subject: [PATCH 12/33] #3304 implemented metadata class and basic export functionality --- .../views/survey-detail.controller.js | 9 ++- .../resources/variable.resource.js | 4 +- .../variablemanagement/domain/CodeBook.java | 66 +++++++++++++++- .../ExportDdiVariablesResourceController.java | 6 +- .../service/VariableManagementService.java | 75 +++++++++++++++++-- 5 files changed, 142 insertions(+), 18 deletions(-) diff --git a/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js b/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js index 41e92391d88..9b2f1656c81 100644 --- a/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js +++ b/mdm-frontend/src/app/legacy/surveymanagement/views/survey-detail.controller.js @@ -56,12 +56,17 @@ angular.module('metadatamanagementApp') .hasAnyAuthority(['ROLE_PUBLISHER', 'ROLE_ADMIN']); ctrl.enableVariableExport = Principal .hasAnyAuthority(['ROLE_PUBLISHER', 'ROLE_ADMIN']); + ctrl.surveyId = null; entity.promise.then(function(survey) { var fetchFn = SurveySearchService.findShadowByIdAndVersion .bind(null, survey.masterId, null, ['nested*','variables','questions', 'instruments', 'dataSets', 'relatedPublications','concepts']); OutdatedVersionNotifier.checkVersionAndNotify(survey, fetchFn); +; + if (survey.release) { + ctrl.surveyId = survey.id + '-' + survey.release.version; + } if (Principal .hasAnyAuthority(['ROLE_PUBLISHER', 'ROLE_DATA_PROVIDER'])) { @@ -182,9 +187,7 @@ angular.module('metadatamanagementApp') * Exports Variables metadata as DDI Codebook XML. */ ctrl.exportVariables = function() { - ExportDdiVariablesResource.exportVariablesAsXml({ - studyId: "foo" - }).then(function(res) { + ExportDdiVariablesResource.exportVariablesAsXml(ctrl.surveyId).then(function(res) { var blob = new Blob([res],{ type: "application/xml;charset=utf-8;" }); diff --git a/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js b/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js index 9704ceea70c..4cf7ef21b40 100644 --- a/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js +++ b/mdm-frontend/src/app/legacy/variablemanagement/resources/variable.resource.js @@ -24,8 +24,8 @@ angular.module('metadatamanagementApp') angular.module('metadatamanagementApp').factory('ExportDdiVariablesResource', ['$http', function($http) { return { - exportVariablesAsXml: function() { - return $http.get('api/variables/exportDDI/xml/:studyId').then(function(response) { + exportVariablesAsXml: function(surveyId) { + return $http.get('api/variables/exportDDI/xml/' + surveyId).then(function(response) { return response.data; }); } diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java index 458c10b8efd..8e2f86e6116 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java @@ -1,8 +1,66 @@ package eu.dzhw.fdz.metadatamanagement.variablemanagement.domain; -public record CodeBook(String name, String address) { - public CodeBook(String name, String address) { - this.name = name; - this.address = address; +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +/** + * Record defining the mapping of the DDI Codebook standard. + */ +@JacksonXmlRootElement(namespace = "ddi:codebook:2_5", localName = "codeBook") +public class CodeBook { + public CodeBook(StdyDscr stdyDscr, DataDscr dataDscr) { + this.stdyDscr = stdyDscr; + this.dataDscr = dataDscr; + } + + @JacksonXmlProperty(localName = "stdyDscr") + private StdyDscr stdyDscr; + @JacksonXmlProperty(localName = "dataDscr") + private DataDscr dataDscr; + + public static class StdyDscr { + public StdyDscr(Citation citation) { + this.citation = citation; + } + + @JacksonXmlProperty(localName = "citation") + Citation citation; + + public static class Citation { + public Citation(TitlStmt titlStmt) { + this.titlStmt = titlStmt; + } + + @JacksonXmlProperty(localName = "titlStmt") + private TitlStmt titlStmt; + + public static class TitlStmt { + public TitlStmt(String titl) { + this.titl = titl; + } + + @JacksonXmlProperty(localName = "titl") + private String titl; + } + } + } + + public static class DataDscr { + public DataDscr(List var) { + this.var = var; + } + + @JacksonXmlProperty(localName = "var") + List var; + + public static class Var { + public Var(String name) { + this.name = name; + } + @JacksonXmlProperty(localName = "name", isAttribute = true) + String name; } + } } diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java index 3adf8f5bb5e..6ecf9bf1814 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java @@ -34,13 +34,13 @@ public class ExportDdiVariablesResourceController { * * @return an XML file */ - @GetMapping(value = "/variables/exportDDI/xml/{studyId:.+}", produces = MediaType.APPLICATION_XML_VALUE) + @GetMapping(value = "/variables/exportDDI/xml/{surveyId:.+}", produces = MediaType.APPLICATION_XML_VALUE) @ResponseBody @Secured(value = {AuthoritiesConstants.PUBLISHER, AuthoritiesConstants.DATA_PROVIDER}) - public ResponseEntity exportVariablesAsXml(@PathVariable String studyId) { + public ResponseEntity exportVariablesAsXml(@PathVariable String surveyId) { ResponseEntity response = new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); try { - response = this.variablesManagementService.exportDdiVariablesAsXML(studyId); + response = this.variablesManagementService.exportDdiVariablesAsXML(surveyId); } catch (PersistenceException ex) { return response; } diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index 0829d50bcb3..51ad5cd72ce 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -1,6 +1,9 @@ package eu.dzhw.fdz.metadatamanagement.variablemanagement.service; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -20,6 +23,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.google.gson.Gson; import eu.dzhw.fdz.metadatamanagement.common.service.CrudService; import eu.dzhw.fdz.metadatamanagement.conceptmanagement.domain.Concept; import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.DataPackage; @@ -28,16 +32,28 @@ import eu.dzhw.fdz.metadatamanagement.projectmanagement.domain.DataAcquisitionProject; import eu.dzhw.fdz.metadatamanagement.questionmanagement.domain.Question; import eu.dzhw.fdz.metadatamanagement.questionmanagement.repository.QuestionRepository; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.dao.exception.ElasticsearchIoException; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.SurveySearchDocument; +import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.VariableSearchDocument; import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchType; import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchUpdateQueueService; import eu.dzhw.fdz.metadatamanagement.surveymanagement.domain.Survey; import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; -import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.CodeBook; import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.Variable; +import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.CodeBook; import eu.dzhw.fdz.metadatamanagement.variablemanagement.repository.VariableRepository; import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.helper.VariableCrudHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.bson.types.Code; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.builder.SearchSourceBuilder; /** * Service for managing the domain object/aggregate {@link Variable}. @@ -58,6 +74,10 @@ public class VariableManagementService implements CrudService { private final VariableCrudHelper crudHelper; + private final RestHighLevelClient client; + + private final Gson gson; + /** * Delete all variables when the dataAcquisitionProject was deleted. * @@ -216,12 +236,12 @@ public Optional readSearchDocument(String id) { /** * Exports all variables belonging to a given study according to the DDI Codebook standard. - * @param studyId the ID of the study + * @param surveyId the ID of the study * @return DDI metadata as XML */ - public ResponseEntity exportDdiVariablesAsXML(String studyId) { + public ResponseEntity exportDdiVariablesAsXML(String surveyId) { try { - CodeBook variableMetadata = this.getDdiVariablesMetadata(); + CodeBook variableMetadata = this.getDdiVariablesMetadata(surveyId); XmlMapper mapper = new XmlMapper(); ByteArrayResource resource = new ByteArrayResource(mapper.writeValueAsBytes(variableMetadata)); HttpHeaders headers = new HttpHeaders(); @@ -238,7 +258,50 @@ public ResponseEntity exportDdiVariablesAsXML(String studyId) { * Collects metadata according to DDI Codebook standard. * @return the metadata */ - private CodeBook getDdiVariablesMetadata() throws JsonProcessingException { - return new CodeBook("Foo", "bar"); + private CodeBook getDdiVariablesMetadata(String surveyId) throws JsonProcessingException { + SearchRequest surveyRequest = new SearchRequest(); + SearchSourceBuilder builderSurveys = new SearchSourceBuilder(); + builderSurveys.query(QueryBuilders.termsQuery("id", surveyId)); + surveyRequest.source(builderSurveys); + surveyRequest.indices("surveys"); + + SearchRequest variablesRequest = new SearchRequest(); + SearchSourceBuilder builderVariables = new SearchSourceBuilder(); + builderVariables.query(QueryBuilders.termsQuery("surveyIds", surveyId)) + .size(10000); + variablesRequest.source(builderVariables); + variablesRequest.indices("variables"); + try { + SearchResponse surveyResponse = client.search(surveyRequest, RequestOptions.DEFAULT); + List surveyHits = Arrays.asList(surveyResponse.getHits().getHits()); + if (surveyHits.size() == 0) { + throw new ElasticsearchException(String.format("Could not find survey with id '%s'", surveyId)); + } + SurveySearchDocument surveyDoc = gson.fromJson( + surveyHits.get(0).getSourceAsString(), SurveySearchDocument.class); + // toDo: Decide on language usage + CodeBook.StdyDscr.Citation.TitlStmt titlStmt = new CodeBook.StdyDscr.Citation.TitlStmt(surveyDoc.getTitle().getEn()); + CodeBook.StdyDscr.Citation citation = new CodeBook.StdyDscr.Citation(titlStmt); + CodeBook.StdyDscr study = new CodeBook.StdyDscr(citation); + SearchResponse variableResponse = client.search(variablesRequest, RequestOptions.DEFAULT); + List hits = Arrays.asList(variableResponse.getHits().getHits()); + if (hits.size() > 0) { + log.info(String.format("Found %d variables for survey '%s'", hits.size(),surveyId)); + List variableList = new ArrayList<>(); + for (var variable : hits) { + VariableSearchDocument variableDoc = gson.fromJson( + variable.getSourceAsString(), VariableSearchDocument.class); + CodeBook.DataDscr.Var varMetadata = new CodeBook.DataDscr.Var(variableDoc.getName()); + variableList.add(varMetadata); + } + CodeBook.DataDscr dataDscr = new CodeBook.DataDscr(variableList); + return new CodeBook(study, dataDscr); + } else { + log.info(String.format("No variables found for studyId '%s'", surveyId)); + } + } catch (IOException e) { + throw new ElasticsearchIoException(e); + } + return null; } } From f2d02c9a16535aea61a20ee95a462ab5280a5c00 Mon Sep 17 00:00:00 2001 From: theresa Date: Mon, 16 Sep 2024 12:30:07 +0200 Subject: [PATCH 13/33] #3304 implemented classes for DDI codebook mapping --- .../domain/ddiCodebook/Catgry.java | 17 +++++ .../domain/ddiCodebook/Citation.java | 12 ++++ .../domain/ddiCodebook/CodeBook.java | 25 +++++++ .../domain/ddiCodebook/DataDscr.java | 14 ++++ .../domain/ddiCodebook/FileDscr.java | 14 ++++ .../domain/ddiCodebook/FileTxt.java | 15 +++++ .../domain/ddiCodebook/LanguageEnum.java | 19 ++++++ .../domain/ddiCodebook/StdyDscr.java | 12 ++++ .../domain/ddiCodebook/TextElement.java | 28 ++++++++ .../domain/ddiCodebook/TitlStmt.java | 15 +++++ .../domain/ddiCodebook/Var.java | 26 ++++++++ .../variablemanagement/domain/CodeBook.java | 66 ------------------- .../ExportDdiVariablesResourceController.java | 51 -------------- 13 files changed, 197 insertions(+), 117 deletions(-) create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Catgry.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Citation.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/CodeBook.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/DataDscr.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileDscr.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileTxt.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/LanguageEnum.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/StdyDscr.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TextElement.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TitlStmt.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Var.java delete mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java delete mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Catgry.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Catgry.java new file mode 100644 index 00000000000..e6acdbcb9b3 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Catgry.java @@ -0,0 +1,17 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class Catgry { + + @JacksonXmlProperty(localName = "catValu") + String catValu; + + @JacksonXmlProperty(localName = "labl") + List labl; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Citation.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Citation.java new file mode 100644 index 00000000000..716c886175e --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Citation.java @@ -0,0 +1,12 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class Citation { + + @JacksonXmlProperty(localName = "titlStmt") + private TitlStmt titlStmt; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/CodeBook.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/CodeBook.java new file mode 100644 index 00000000000..dff4a1cafd5 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/CodeBook.java @@ -0,0 +1,25 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import lombok.AllArgsConstructor; + +/** + * Record defining the mapping of the DDI Codebook standard. + */ +@AllArgsConstructor +@JacksonXmlRootElement(namespace = "ddi:codebook:2_5", localName = "codeBook") +public class CodeBook { + + @JacksonXmlProperty(localName = "stdyDscr") + private StdyDscr stdyDscr; + + @JacksonXmlProperty(localName = "fileDscr") + private List fileDscr; + + @JacksonXmlProperty(localName = "dataDscr") + private DataDscr dataDscr; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/DataDscr.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/DataDscr.java new file mode 100644 index 00000000000..9a4e0a57e21 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/DataDscr.java @@ -0,0 +1,14 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class DataDscr { + + @JacksonXmlProperty(localName = "var") + List var; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileDscr.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileDscr.java new file mode 100644 index 00000000000..c4ede7e849a --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileDscr.java @@ -0,0 +1,14 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class FileDscr { + + @JacksonXmlProperty(localName = "ID", isAttribute = true) + String id; + + @JacksonXmlProperty(localName = "fileTxt") + FileTxt fileTxt; +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileTxt.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileTxt.java new file mode 100644 index 00000000000..5f9e18db2ba --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/FileTxt.java @@ -0,0 +1,15 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class FileTxt { + + @JacksonXmlProperty(localName = "fileName") + String fileName; + + @JacksonXmlProperty(localName = "fileCont") + TextElement fileCont; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/LanguageEnum.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/LanguageEnum.java new file mode 100644 index 00000000000..c3c914ab36c --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/LanguageEnum.java @@ -0,0 +1,19 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +public enum LanguageEnum { + de("de"), en("en"); + + /** + * The language string + */ + public final String languageString; + + /** + * Construct the enum. + * + * @param languageString The language string. + */ + LanguageEnum(String languageString) { + this.languageString = languageString; + } +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/StdyDscr.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/StdyDscr.java new file mode 100644 index 00000000000..08bf01808e0 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/StdyDscr.java @@ -0,0 +1,12 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class StdyDscr { + + @JacksonXmlProperty(localName = "citation") + Citation citation; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TextElement.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TextElement.java new file mode 100644 index 00000000000..e38c29434b7 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TextElement.java @@ -0,0 +1,28 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText; +import lombok.AllArgsConstructor; + +/** + * General element for a language annotated XML element containing a string, + * e.g. labels (labl in DDI standard). + */ +@AllArgsConstructor +public class TextElement { + + @JacksonXmlProperty(localName = "xml:lang", isAttribute = true) + private LanguageEnum lang; + + @JacksonXmlText + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TitlStmt.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TitlStmt.java new file mode 100644 index 00000000000..d5172cfd010 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/TitlStmt.java @@ -0,0 +1,15 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class TitlStmt { + + @JacksonXmlProperty(localName = "titl") + private TextElement titl; + + @JacksonXmlProperty(localName = "parTitl") + private TextElement parTitle; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Var.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Var.java new file mode 100644 index 00000000000..27bc7970bbe --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/domain/ddiCodebook/Var.java @@ -0,0 +1,26 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook; + +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class Var { + + @JacksonXmlProperty(localName = "name", isAttribute = true) + String name; + + @JacksonXmlProperty(localName = "files", isAttribute = true) + String files; + + @JacksonXmlProperty(localName = "labl") + List labl; + + @JacksonXmlProperty(localName = "qstn") + List qstn; + + @JacksonXmlProperty(localName = "catgry") + List catgry; + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java deleted file mode 100644 index 8e2f86e6116..00000000000 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/domain/CodeBook.java +++ /dev/null @@ -1,66 +0,0 @@ -package eu.dzhw.fdz.metadatamanagement.variablemanagement.domain; - -import java.util.List; - -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; - -/** - * Record defining the mapping of the DDI Codebook standard. - */ -@JacksonXmlRootElement(namespace = "ddi:codebook:2_5", localName = "codeBook") -public class CodeBook { - public CodeBook(StdyDscr stdyDscr, DataDscr dataDscr) { - this.stdyDscr = stdyDscr; - this.dataDscr = dataDscr; - } - - @JacksonXmlProperty(localName = "stdyDscr") - private StdyDscr stdyDscr; - @JacksonXmlProperty(localName = "dataDscr") - private DataDscr dataDscr; - - public static class StdyDscr { - public StdyDscr(Citation citation) { - this.citation = citation; - } - - @JacksonXmlProperty(localName = "citation") - Citation citation; - - public static class Citation { - public Citation(TitlStmt titlStmt) { - this.titlStmt = titlStmt; - } - - @JacksonXmlProperty(localName = "titlStmt") - private TitlStmt titlStmt; - - public static class TitlStmt { - public TitlStmt(String titl) { - this.titl = titl; - } - - @JacksonXmlProperty(localName = "titl") - private String titl; - } - } - } - - public static class DataDscr { - public DataDscr(List var) { - this.var = var; - } - - @JacksonXmlProperty(localName = "var") - List var; - - public static class Var { - public Var(String name) { - this.name = name; - } - @JacksonXmlProperty(localName = "name", isAttribute = true) - String name; - } - } -} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java deleted file mode 100644 index 6ecf9bf1814..00000000000 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/rest/ExportDdiVariablesResourceController.java +++ /dev/null @@ -1,51 +0,0 @@ -package eu.dzhw.fdz.metadatamanagement.variablemanagement.rest; - -import java.io.IOException; - -import javax.persistence.PersistenceException; - -import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; -import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.VariableManagementService; -import lombok.RequiredArgsConstructor; - -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.annotation.Secured; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -/** - * Controller for exporting variable metadata as DDI codebook. - */ -@Controller -@RequestMapping("/api") -@RequiredArgsConstructor -public class ExportDdiVariablesResourceController { - - private final VariableManagementService variablesManagementService; - - /** - * Exports all variables metadata belonging to the given survey ID as DDI Codebook. - * - * @return an XML file - */ - @GetMapping(value = "/variables/exportDDI/xml/{surveyId:.+}", produces = MediaType.APPLICATION_XML_VALUE) - @ResponseBody - @Secured(value = {AuthoritiesConstants.PUBLISHER, AuthoritiesConstants.DATA_PROVIDER}) - public ResponseEntity exportVariablesAsXml(@PathVariable String surveyId) { - ResponseEntity response = new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); - try { - response = this.variablesManagementService.exportDdiVariablesAsXML(surveyId); - } catch (PersistenceException ex) { - return response; - } - - return response; - } - -} From 0bdededa8dabddb83f0a22f42ed2a0635f3f25bf Mon Sep 17 00:00:00 2001 From: theresa Date: Mon, 16 Sep 2024 12:31:28 +0200 Subject: [PATCH 14/33] #3304 refactored ddi codebook export --- .../ExportDdiVariablesResourceController.java | 49 +++++ .../service/DataPackageDdiService.java | 188 ++++++++++++++++++ .../service/DataPackageManagementService.java | 23 +++ .../service/VariableManagementService.java | 109 +--------- 4 files changed, 267 insertions(+), 102 deletions(-) create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/rest/ExportDdiVariablesResourceController.java create mode 100644 src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageDdiService.java diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/rest/ExportDdiVariablesResourceController.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/rest/ExportDdiVariablesResourceController.java new file mode 100644 index 00000000000..c865ffe82f8 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/rest/ExportDdiVariablesResourceController.java @@ -0,0 +1,49 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.rest; + +import javax.persistence.PersistenceException; + +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.service.DataPackageDdiService; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.service.DataPackageManagementService; +import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; +import lombok.RequiredArgsConstructor; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * Controller for exporting variable metadata as DDI codebook. + */ +@Controller +@RequestMapping("/api") +@RequiredArgsConstructor +public class ExportDdiVariablesResourceController { + + private final DataPackageDdiService dataPackageDdiService; + + /** + * Exports all variables metadata belonging to the given dataPackage ID as DDI Codebook XML file. + * + * @return an XML file + */ + @GetMapping(value = "/data-packages/exportDDI/xml/{dataPackageId:.+}", produces = MediaType.APPLICATION_XML_VALUE) + @ResponseBody + @Secured(value = {AuthoritiesConstants.PUBLISHER, AuthoritiesConstants.DATA_PROVIDER}) + public ResponseEntity exportVariablesAsXml(@PathVariable String dataPackageId) { + ResponseEntity response = new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); + try { + response = this.dataPackageDdiService.exportDdiVariablesAsXML(dataPackageId); + } catch (PersistenceException ex) { + return response; + } + + return response; + } + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageDdiService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageDdiService.java new file mode 100644 index 00000000000..bfff6659a15 --- /dev/null +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageDdiService.java @@ -0,0 +1,188 @@ +package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.service; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.google.gson.Gson; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.DataPackage; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.Catgry; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.Citation; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.CodeBook; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.DataDscr; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.FileDscr; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.FileTxt; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.LanguageEnum; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.StdyDscr; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.TextElement; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.TitlStmt; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.Var; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.elasticsearch.client.RestHighLevelClient; + +import org.springframework.core.io.ByteArrayResource; +import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +/** + * Service for construction DDI codebook metadata for all veriables of a {@link DataPackage}. + * @since Sep 2024 + * @author Theresa Möller + */ +@Service +@RepositoryEventHandler +@RequiredArgsConstructor +@Slf4j +public class DataPackageDdiService { + + private final RestHighLevelClient client; + + private final Gson gson; + + /** + * Exports all variables belonging to a given datapackage according to the DDI Codebook standard. + * @param dataPackageId the ID of the study + * @return DDI metadata as XML + */ + public ResponseEntity exportDdiVariablesAsXML(String dataPackageId) { + try { + CodeBook variableMetadata = this.getDdiVariablesMetadata(dataPackageId); + XmlMapper mapper = new XmlMapper(); + ByteArrayResource resource = new ByteArrayResource(mapper.writeValueAsBytes(variableMetadata)); + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Disposition", "attachment; filename=Variables_PID_MDM_Export.xml"); + return ResponseEntity.ok() + .headers(headers) + .body(resource); + } catch (IOException ex) { + return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); + } + } + + /** + * Collects variables metadata according to DDI Codebook standard. + * @return the metadata + */ + private CodeBook getDdiVariablesMetadata(String dataPackageId) throws JsonProcessingException { + StdyDscr stdyDscr = this.getDdiStdyDscr(); + + List fileDscrList = new ArrayList<>(); + // for each dataset of the data package + for (int i = 0; i < 3; i++) { + //todo make a list of all added datasets and do add there variables later on + fileDscrList.add(this.getDdiFileDsrc()); + } + + List varList = new ArrayList<>(); + // for each variable of the data package + for (int j = 0; j < 10; j++) { + varList.add(this.getDdiVar()); + } + DataDscr dataDscr = new DataDscr(varList); + CodeBook codeBook = new CodeBook(stdyDscr, fileDscrList, dataDscr); + + return codeBook; + + +// SearchRequest surveyRequest = new SearchRequest(); +// SearchSourceBuilder builderSurveys = new SearchSourceBuilder(); +// builderSurveys.query(QueryBuilders.termsQuery("id", surveyId)); +// surveyRequest.source(builderSurveys); +// surveyRequest.indices("surveys"); +// +// SearchRequest variablesRequest = new SearchRequest(); +// SearchSourceBuilder builderVariables = new SearchSourceBuilder(); +// builderVariables.query(QueryBuilders.termsQuery("surveyIds", surveyId)) +// .size(10000); +// variablesRequest.source(builderVariables); +// variablesRequest.indices("variables"); +// try { +// SearchResponse surveyResponse = client.search(surveyRequest, RequestOptions.DEFAULT); +// List surveyHits = Arrays.asList(surveyResponse.getHits().getHits()); +// if (surveyHits.size() == 0) { +// throw new ElasticsearchException(String.format("Could not find survey with id '%s'", surveyId)); +// } +// SurveySearchDocument surveyDoc = gson.fromJson( +// surveyHits.get(0).getSourceAsString(), SurveySearchDocument.class); +// // toDo: Decide on language usage +// CodeBook.StdyDscr.Citation.TitlStmt titlStmt = new CodeBook.StdyDscr.Citation.TitlStmt(surveyDoc.getTitle().getEn()); +// CodeBook.StdyDscr.Citation citation = new CodeBook.StdyDscr.Citation(titlStmt); +// CodeBook.StdyDscr study = new CodeBook.StdyDscr(citation); +// SearchResponse variableResponse = client.search(variablesRequest, RequestOptions.DEFAULT); +// List hits = Arrays.asList(variableResponse.getHits().getHits()); +// if (hits.size() > 0) { +// log.info(String.format("Found %d variables for survey '%s'", hits.size(),surveyId)); +// List variableList = new ArrayList<>(); +// for (var variable : hits) { +// VariableSearchDocument variableDoc = gson.fromJson( +// variable.getSourceAsString(), VariableSearchDocument.class); +// CodeBook.DataDscr.Var varMetadata = new CodeBook.DataDscr.Var(variableDoc.getName()); +// variableList.add(varMetadata); +// } +// CodeBook.DataDscr dataDscr = new CodeBook.DataDscr(variableList); +// return new CodeBook(study, dataDscr); +// } else { +// log.info(String.format("No variables found for studyId '%s'", surveyId)); +// } +// } catch (IOException e) { +// throw new ElasticsearchIoException(e); +// } + //return null; + } + + /** + * + * @return + */ + private Var getDdiVar() { + String name = "Variable ID"; + String files = "Dataset ID"; + List varLablList = new ArrayList<>(); + varLablList.add(new TextElement(LanguageEnum.de, "Variable Label in German")); + varLablList.add(new TextElement(LanguageEnum.en, "Variable Label in English")); + List qstnList = new ArrayList<>(); + // possibly empty + qstnList.add(new TextElement(LanguageEnum.de, "Related Question label in German")); + qstnList.add(new TextElement(LanguageEnum.en, "Related Question label in English")); + List catgryList = new ArrayList<>(); + for (int k = 0; k < 5; k++) { + // only for nominal/ordinal + String catValu = "Value"; + List catLablList = new ArrayList<>(); + catLablList.add(new TextElement(LanguageEnum.de, "Value Label in German")); + catLablList.add(new TextElement(LanguageEnum.en, "Value Label in English")); + catgryList.add(new Catgry(catValu, catLablList)); + } + return new Var(name, files, varLablList, qstnList, catgryList); + } + + /** + * + * @return + */ + private FileDscr getDdiFileDsrc() { + String id = "Dataset ID"; + String fileName = "Dataset ID"; + TextElement fileCont = new TextElement(LanguageEnum.de, "Dataset Title in German"); + FileTxt fileTxt = new FileTxt(fileName, fileCont); + return new FileDscr(id, fileTxt); + } + + /** + * + * @return + */ + private StdyDscr getDdiStdyDscr() { + TextElement titl = new TextElement(LanguageEnum.de, "Data Package Title in German"); + TextElement parTitl = new TextElement(LanguageEnum.en, "Data Package Title in English"); + Citation citation = new Citation(new TitlStmt(titl, parTitl)); + return new StdyDscr(citation); + } + +} diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageManagementService.java index aacef3e7ae5..1e2b7f8959f 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/datapackagemanagement/service/DataPackageManagementService.java @@ -1,22 +1,41 @@ package eu.dzhw.fdz.metadatamanagement.datapackagemanagement.service; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.springframework.core.io.ByteArrayResource; import org.springframework.data.rest.core.annotation.HandleAfterCreate; import org.springframework.data.rest.core.annotation.HandleAfterDelete; import org.springframework.data.rest.core.annotation.HandleAfterSave; import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.google.gson.Gson; import eu.dzhw.fdz.metadatamanagement.analysispackagemanagement.domain.AnalysisPackage; import eu.dzhw.fdz.metadatamanagement.common.service.CrudService; import eu.dzhw.fdz.metadatamanagement.conceptmanagement.domain.Concept; import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.DataPackage; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.Catgry; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.Citation; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.DataDscr; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.FileDscr; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.FileTxt; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.LanguageEnum; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.StdyDscr; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.TextElement; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.TitlStmt; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.Var; import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.repository.DataPackageRepository; import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.service.helper.DataPackageCrudHelper; import eu.dzhw.fdz.metadatamanagement.datasetmanagement.domain.DataSet; @@ -34,8 +53,11 @@ import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchUpdateQueueService; import eu.dzhw.fdz.metadatamanagement.surveymanagement.domain.Survey; import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; +import eu.dzhw.fdz.metadatamanagement.datapackagemanagement.domain.ddiCodebook.CodeBook; import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.Variable; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.elasticsearch.client.RestHighLevelClient; /** * Service for managing the domain object/aggregate {@link DataPackage}. @@ -45,6 +67,7 @@ @Service @RepositoryEventHandler @RequiredArgsConstructor +@Slf4j public class DataPackageManagementService implements CrudService { private final DataPackageRepository dataPackageRepository; diff --git a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java index 51ad5cd72ce..d6017438d6f 100644 --- a/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java +++ b/src/main/java/eu/dzhw/fdz/metadatamanagement/variablemanagement/service/VariableManagementService.java @@ -1,28 +1,10 @@ package eu.dzhw.fdz.metadatamanagement.variablemanagement.service; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.data.rest.core.annotation.HandleAfterCreate; -import org.springframework.data.rest.core.annotation.HandleAfterDelete; -import org.springframework.data.rest.core.annotation.HandleAfterSave; -import org.springframework.data.rest.core.annotation.RepositoryEventHandler; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.annotation.Secured; -import org.springframework.stereotype.Service; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.google.gson.Gson; import eu.dzhw.fdz.metadatamanagement.common.service.CrudService; import eu.dzhw.fdz.metadatamanagement.conceptmanagement.domain.Concept; @@ -32,28 +14,23 @@ import eu.dzhw.fdz.metadatamanagement.projectmanagement.domain.DataAcquisitionProject; import eu.dzhw.fdz.metadatamanagement.questionmanagement.domain.Question; import eu.dzhw.fdz.metadatamanagement.questionmanagement.repository.QuestionRepository; -import eu.dzhw.fdz.metadatamanagement.searchmanagement.dao.exception.ElasticsearchIoException; -import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.SurveySearchDocument; -import eu.dzhw.fdz.metadatamanagement.searchmanagement.documents.VariableSearchDocument; import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchType; import eu.dzhw.fdz.metadatamanagement.searchmanagement.service.ElasticsearchUpdateQueueService; import eu.dzhw.fdz.metadatamanagement.surveymanagement.domain.Survey; import eu.dzhw.fdz.metadatamanagement.usermanagement.security.AuthoritiesConstants; import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.Variable; -import eu.dzhw.fdz.metadatamanagement.variablemanagement.domain.CodeBook; import eu.dzhw.fdz.metadatamanagement.variablemanagement.repository.VariableRepository; import eu.dzhw.fdz.metadatamanagement.variablemanagement.service.helper.VariableCrudHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.bson.types.Code; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.builder.SearchSourceBuilder; + +import org.springframework.data.rest.core.annotation.HandleAfterCreate; +import org.springframework.data.rest.core.annotation.HandleAfterDelete; +import org.springframework.data.rest.core.annotation.HandleAfterSave; +import org.springframework.data.rest.core.annotation.RepositoryEventHandler; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Service; /** * Service for managing the domain object/aggregate {@link Variable}. @@ -63,7 +40,6 @@ @Service @RepositoryEventHandler @RequiredArgsConstructor -@Slf4j public class VariableManagementService implements CrudService { private final QuestionRepository questionRepository; @@ -233,75 +209,4 @@ public Optional read(String id) { public Optional readSearchDocument(String id) { return crudHelper.readSearchDocument(id); } - - /** - * Exports all variables belonging to a given study according to the DDI Codebook standard. - * @param surveyId the ID of the study - * @return DDI metadata as XML - */ - public ResponseEntity exportDdiVariablesAsXML(String surveyId) { - try { - CodeBook variableMetadata = this.getDdiVariablesMetadata(surveyId); - XmlMapper mapper = new XmlMapper(); - ByteArrayResource resource = new ByteArrayResource(mapper.writeValueAsBytes(variableMetadata)); - HttpHeaders headers = new HttpHeaders(); - headers.add("Content-Disposition", "attachment; filename=Variables_PID_MDM_Export.xml"); - return ResponseEntity.ok() - .headers(headers) - .body(resource); - } catch (IOException ex) { - return new ResponseEntity<>(null, null, HttpStatus.NOT_FOUND); - } - } - - /** - * Collects metadata according to DDI Codebook standard. - * @return the metadata - */ - private CodeBook getDdiVariablesMetadata(String surveyId) throws JsonProcessingException { - SearchRequest surveyRequest = new SearchRequest(); - SearchSourceBuilder builderSurveys = new SearchSourceBuilder(); - builderSurveys.query(QueryBuilders.termsQuery("id", surveyId)); - surveyRequest.source(builderSurveys); - surveyRequest.indices("surveys"); - - SearchRequest variablesRequest = new SearchRequest(); - SearchSourceBuilder builderVariables = new SearchSourceBuilder(); - builderVariables.query(QueryBuilders.termsQuery("surveyIds", surveyId)) - .size(10000); - variablesRequest.source(builderVariables); - variablesRequest.indices("variables"); - try { - SearchResponse surveyResponse = client.search(surveyRequest, RequestOptions.DEFAULT); - List surveyHits = Arrays.asList(surveyResponse.getHits().getHits()); - if (surveyHits.size() == 0) { - throw new ElasticsearchException(String.format("Could not find survey with id '%s'", surveyId)); - } - SurveySearchDocument surveyDoc = gson.fromJson( - surveyHits.get(0).getSourceAsString(), SurveySearchDocument.class); - // toDo: Decide on language usage - CodeBook.StdyDscr.Citation.TitlStmt titlStmt = new CodeBook.StdyDscr.Citation.TitlStmt(surveyDoc.getTitle().getEn()); - CodeBook.StdyDscr.Citation citation = new CodeBook.StdyDscr.Citation(titlStmt); - CodeBook.StdyDscr study = new CodeBook.StdyDscr(citation); - SearchResponse variableResponse = client.search(variablesRequest, RequestOptions.DEFAULT); - List hits = Arrays.asList(variableResponse.getHits().getHits()); - if (hits.size() > 0) { - log.info(String.format("Found %d variables for survey '%s'", hits.size(),surveyId)); - List variableList = new ArrayList<>(); - for (var variable : hits) { - VariableSearchDocument variableDoc = gson.fromJson( - variable.getSourceAsString(), VariableSearchDocument.class); - CodeBook.DataDscr.Var varMetadata = new CodeBook.DataDscr.Var(variableDoc.getName()); - variableList.add(varMetadata); - } - CodeBook.DataDscr dataDscr = new CodeBook.DataDscr(variableList); - return new CodeBook(study, dataDscr); - } else { - log.info(String.format("No variables found for studyId '%s'", surveyId)); - } - } catch (IOException e) { - throw new ElasticsearchIoException(e); - } - return null; - } } From 428e589055aadb2025524817cbb2e2e7584afa62 Mon Sep 17 00:00:00 2001 From: theresa Date: Mon, 16 Sep 2024 12:32:29 +0200 Subject: [PATCH 15/33] #3304 refactored frontend ddi codebook export --- .../resources/dataPackage.resource.js | 16 +++++++++++++ .../views/data-package-detail.controller.js | 24 ++++++++++++++++++- .../views/data-package-detail.html.tmpl | 16 ++++++++++--- .../views/survey-detail.controller.js | 24 ++++--------------- .../resources/variable.resource.js | 15 ------------ 5 files changed, 56 insertions(+), 39 deletions(-) diff --git a/mdm-frontend/src/app/legacy/datapackagemanagement/resources/dataPackage.resource.js b/mdm-frontend/src/app/legacy/datapackagemanagement/resources/dataPackage.resource.js index 3f55ec07c7f..386864e4ca8 100644 --- a/mdm-frontend/src/app/legacy/datapackagemanagement/resources/dataPackage.resource.js +++ b/mdm-frontend/src/app/legacy/datapackagemanagement/resources/dataPackage.resource.js @@ -25,3 +25,19 @@ angular.module('metadatamanagementApp') }); }]); + + /** + * Method to request the endpoint that downloads all variables of the data package as a DDI-formatted XML file. + * We could not put this into the "DataPackageResource"-schema (above), because the URLs would not match. + */ + angular.module('metadatamanagementApp').factory('ExportDdiVariablesResource', ['$http', + function($http) { + return { + exportVariablesAsXml: function(dataPackageId) { + return $http.get('api/data-packages/exportDDI/xml/' + dataPackageId).then(function(response) { + return response.data; + }); + } + } + }]); + diff --git a/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.controller.js b/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.controller.js index 5ae229afc46..bce54e94843 100644 --- a/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.controller.js +++ b/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.controller.js @@ -35,6 +35,7 @@ angular.module('metadatamanagementApp') 'blockUI', '$mdSidenav', 'ContainsOnlyQualitativeDataChecker', + 'ExportDdiVariablesResource', function(entity, MessageBus, PageMetadataService, @@ -48,7 +49,8 @@ angular.module('metadatamanagementApp') ProjectUpdateAccessService, $scope, $timeout, $document, DataPackageOverviewResource, OutdatedVersionNotifier, DataPackageSearchService, $log, - blockUI, $mdSidenav, ContainsOnlyQualitativeDataChecker) { + blockUI, $mdSidenav, ContainsOnlyQualitativeDataChecker, + ExportDdiVariablesResource) { blockUI.start(); SearchResultNavigatorService .setSearchIndex($stateParams['search-result-index']); @@ -89,6 +91,8 @@ angular.module('metadatamanagementApp') .hasAnyAuthority(['ROLE_PUBLISHER', 'ROLE_ADMIN']); ctrl.showRemarks = Principal .hasAnyAuthority(['ROLE_PUBLISHER']); + ctrl.enableVariableExport = Principal + .hasAnyAuthority(['ROLE_PUBLISHER', 'ROLE_ADMIN']); var bowser = $rootScope.bowser; @@ -306,5 +310,23 @@ angular.module('metadatamanagementApp') } return true; } + + /** + * Exports Variables metadata as DDI Codebook XML. + */ + ctrl.exportVariables = function() { + console.log(ctrl.dataPackage) + ExportDdiVariablesResource.exportVariablesAsXml(ctrl.dataPackage.id).then(function(res) { + var blob = new Blob([res],{ + type: "application/xml;charset=utf-8;" + }); + var downloadLink = document.createElement('a'); + const fileName = 'mdm_export_ddi_variables_' + ctrl.dataPackage.id + '.xml' + downloadLink.setAttribute('download', fileName); + downloadLink.setAttribute('href', window.URL.createObjectURL(blob)); + downloadLink.click(); + $scope.isDownloadingData = false; + }) + } }]); diff --git a/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.html.tmpl b/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.html.tmpl index 30049515cb4..d1a447454c1 100644 --- a/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.html.tmpl +++ b/mdm-frontend/src/app/legacy/datapackagemanagement/views/data-package-detail.html.tmpl @@ -6,10 +6,20 @@
-
+

- +
+ + + + Variablen als XML nach DDI Standard exportieren + + DDI + +