package eu.eudat.logic.managers; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.configurations.dynamicgrant.DynamicGrantConfiguration; import eu.eudat.configurations.dynamicgrant.entities.Property; import eu.eudat.data.dao.criteria.*; import eu.eudat.data.dao.entities.*; import eu.eudat.data.entities.Organisation; import eu.eudat.data.entities.Researcher; import eu.eudat.data.entities.*; import eu.eudat.data.enumeration.notification.ActiveStatus; import eu.eudat.data.enumeration.notification.ContactType; import eu.eudat.data.enumeration.notification.NotificationType; import eu.eudat.data.enumeration.notification.NotifyState; import eu.eudat.data.query.items.item.dmp.DataManagementPlanCriteriaRequest; import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem; import eu.eudat.data.query.items.table.dmp.DataManagementPlanTableRequest; import eu.eudat.data.query.items.table.dmp.DataManagmentPlanPublicTableRequest; import eu.eudat.exceptions.datamanagementplan.DMPNewVersionException; import eu.eudat.exceptions.datamanagementplan.DMPWithDatasetsDeleteException; import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.builders.entity.UserInfoBuilder; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.forms.VisibilityRuleService; import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.logic.services.utilities.UtilitiesService; import eu.eudat.logic.utilities.builders.XmlBuilder; import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; import eu.eudat.logic.utilities.documents.types.ParagraphStyle; import eu.eudat.logic.utilities.documents.word.WordBuilder; import eu.eudat.logic.utilities.documents.xml.ExportXmlBuilder; import eu.eudat.models.HintedModelFactory; import eu.eudat.models.data.datasetprofile.DatasetProfileListingModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.datasetwizard.DatasetsToBeFinalized; import eu.eudat.models.data.dmp.*; import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.Field; import eu.eudat.models.data.funder.FunderDMPEditorModel; import eu.eudat.models.data.grant.GrantDMPEditorModel; import eu.eudat.models.data.helpermodels.Tuple; import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.listingmodels.DataManagementPlanListingModel; import eu.eudat.models.data.listingmodels.DataManagementPlanOverviewModel; import eu.eudat.models.data.listingmodels.DatasetListingModel; import eu.eudat.models.data.listingmodels.UserInfoListingModel; import eu.eudat.models.data.project.ProjectDMPEditorModel; import eu.eudat.models.data.rda.RDAExportModel; import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.user.composite.PagedDatasetProfile; import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.queryable.QueryableList; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.core.io.FileSystemResource; import org.springframework.http.*; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import java.io.*; import java.math.BigInteger; import java.nio.file.Files; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; @Component public class DataManagementPlanManager { private static final Logger logger = LoggerFactory.getLogger(DataManagementPlanManager.class); private final Map notificationPaths = Stream.of(new Object[][] { {NotificationType.DMP_MODIFIED, "/plans/edit"}, {NotificationType.DMP_PUBLISH, "/plans/publicEdit"}, {NotificationType.DMP_FINALISED, "/plans/edit"}, {NotificationType.DMP_MODIFIED_FINALISED, "/plans/edit"} }).collect(Collectors.toMap(data -> (NotificationType) data[0], data -> (String) data[1])); private ApiContext apiContext; private DatasetManager datasetManager; private UtilitiesService utilitiesService; private DatabaseRepository databaseRepository; private Environment environment; @Autowired public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, Environment environment) { this.apiContext = apiContext; this.datasetManager = datasetManager; this.utilitiesService = apiContext.getUtilitiesService(); this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); this.environment = environment; } public DataTableData getPaged(DataManagementPlanTableRequest dataManagementPlanTableRequest, Principal principal, String fieldsGroup) throws Exception { UUID principalID = principal.getId(); QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(dataManagementPlanTableRequest.getCriteria()); List roles = new LinkedList<>(); if (dataManagementPlanTableRequest.getCriteria().getRole() != null) roles.add(dataManagementPlanTableRequest.getCriteria().getRole()); QueryableList authItems = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getAuthenticated(items, principalID, roles); QueryableList pagedItems = PaginationManager.applyPaging(authItems, dataManagementPlanTableRequest); DataTableData dataTable = new DataTableData<>(); CompletableFuture itemsFuture; if (fieldsGroup.equals("listing")) { itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class)) .selectAsync(item -> { item.setDataset( item.getDataset().stream() .filter(dataset -> !dataset.getStatus().equals(Dataset.Status.DELETED.getValue()) && !dataset.getStatus().equals(Dataset.Status.CANCELED.getValue())).collect(Collectors.toList()).stream() .filter(dataset -> dataset.getDmp().getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getId().equals(principalID) || dataset.getDmp().getUsers().stream() .filter(x -> x.getUser().getId().equals(principalID)) .collect(Collectors.toList()).size() > 0) .collect(Collectors.toSet())); return new DataManagementPlanListingModel().fromDataModelDatasets(item); }) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } else if (fieldsGroup.equals("autocomplete")) { itemsFuture = pagedItems .selectAsync(item -> new DataManagementPlanListingModel().fromDataModelAutoComplete(item)) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } else { itemsFuture = pagedItems .selectAsync(item -> new DataManagementPlanListingModel().fromDataModelAssociatedProfiles(item)) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } CompletableFuture countFuture = authItems.countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count)); CompletableFuture.allOf(itemsFuture, countFuture).join(); return dataTable; } public DataTableData getPublicPaged(DataManagmentPlanPublicTableRequest dataManagementPlanPublicTableRequest, String fieldsGroup, Principal principal) throws Exception { dataManagementPlanPublicTableRequest.setQuery(databaseRepository.getDmpDao().asQueryable().withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class))); QueryableList items = dataManagementPlanPublicTableRequest.applyCriteria(); if (principal.getId() != null && dataManagementPlanPublicTableRequest.getCriteria().getRole() != null) { items.where((builder, root) -> { Join userJoin = root.join("users", JoinType.LEFT); return builder.and(builder.equal(userJoin.join("user", JoinType.LEFT).get("id"), principal.getId()), builder.equal(userJoin.get("role"), dataManagementPlanPublicTableRequest.getCriteria().getRole())); }); } QueryableList pagedItems = PaginationManager.applyPaging(items, dataManagementPlanPublicTableRequest); DataTableData dataTable = new DataTableData<>(); CompletableFuture itemsFuture; if (fieldsGroup.equals("listing")) { itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class)) .selectAsync(item -> { item.setDataset( item.getDataset().stream() .filter(dataset -> dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())).collect(Collectors.toSet())); return new DataManagementPlanListingModel().fromDataModelDatasets(item); }) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } else { itemsFuture = pagedItems .selectAsync(item -> new DataManagementPlanListingModel().fromDataModel(item)) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } CompletableFuture countFuture = items.countAsync().whenComplete((count, throwable) -> { dataTable.setTotalCount(count); }); CompletableFuture.allOf(itemsFuture, countFuture).join(); return dataTable; } public void unlock(UUID uuid) throws Exception { apiContext.getOperationsContext().getDatabaseRepository().getDmpDao() .asQueryable().where((builder, root) -> builder.equal(root.get("id"), uuid)) .update(root -> root.get("status"), DMP.DMPStatus.ACTIVE.getValue()); return; } public File getWordDocument(String id, Principal principal, ConfigLoader configLoader) throws IOException { return this.getWordDocument(id, principal, configLoader, false); } public File getWordDocument(String id, Principal principal, ConfigLoader configLoader, Boolean versioned) throws IOException { WordBuilder wordBuilder = new WordBuilder(); VisibilityRuleService visibilityRuleService = this.utilitiesService.getVisibilityRuleService(); DatasetWizardModel dataset = new DatasetWizardModel(); XWPFDocument document = configLoader.getDocument(); eu.eudat.data.entities.DMP dmpEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (!dmpEntity.isPublic() && dmpEntity.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) throw new UnauthorisedException(); // DMP info on top of the document. wordBuilder.addParagraphContent("Data Management Plan Information", document, ParagraphStyle.HEADER1, BigInteger.ZERO); // DMP title custom style. wordBuilder.addParagraphContent(dmpEntity.getLabel(), document, ParagraphStyle.HEADER2, BigInteger.ZERO); wordBuilder.addParagraphContent(dmpEntity.getDescription(), document, ParagraphStyle.TEXT, BigInteger.ZERO); wordBuilder.addParagraphContent("Funder", document, ParagraphStyle.HEADER3, BigInteger.ZERO); if (dmpEntity.getGrant().getFunder() != null) wordBuilder.addParagraphContent(dmpEntity.getGrant().getFunder().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); wordBuilder.addParagraphContent("Grant", document, ParagraphStyle.HEADER3, BigInteger.ZERO); wordBuilder.addParagraphContent(dmpEntity.getGrant().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); wordBuilder.addParagraphContent("Organisations", document, ParagraphStyle.HEADER3, BigInteger.ZERO); if (dmpEntity.getOrganisations().size() > 0) { wordBuilder.addParagraphContent(dmpEntity.getOrganisations().stream().map(Organisation::getLabel).collect(Collectors.joining(", ")) , document, ParagraphStyle.TEXT, BigInteger.ZERO); } wordBuilder.addParagraphContent("Researchers", document, ParagraphStyle.HEADER3, BigInteger.ZERO); if (dmpEntity.getResearchers().size() > 0) { wordBuilder.addParagraphContent(dmpEntity.getResearchers().stream().map(Researcher::getLabel).collect(Collectors.joining(", ")) , document, ParagraphStyle.TEXT, BigInteger.ZERO); } /*wordBuilder.addParagraphContent("DMP Profile", document, ParagraphStyle.HEADER2, BigInteger.ZERO); if (dmpEntity.getProfile() != null){ wordBuilder.addParagraphContent(dmpEntity.getProfile().getLabel(), document, ParagraphStyle.TEXT, BigInteger.ZERO); }*/ // Page break at the end of the DMP title. XWPFParagraph parBreakDMP = document.createParagraph(); parBreakDMP.setPageBreak(true); wordBuilder.addParagraphContent("Datasets", document, ParagraphStyle.HEADER1, BigInteger.ZERO); // Space below Datasets. XWPFParagraph parBreakDatasets = document.createParagraph(); dmpEntity.getDataset().stream() .filter(item -> item.getStatus() != Dataset.Status.CANCELED.getValue()) .filter(item -> item.getStatus() != Dataset.Status.DELETED.getValue()) .forEach(datasetEntity -> { Map properties = new HashMap<>(); if (datasetEntity.getProperties() != null) { JSONObject jObject = new JSONObject(datasetEntity.getProperties()); properties = jObject.toMap(); } // Custom style for the Dataset title. //wordBuilder.addParagraphContent("Title: " + datasetEntity.getLabel(), document, ParagraphStyle.HEADER1, BigInteger.ZERO); XWPFParagraph datasetLabelParagraph = document.createParagraph(); datasetLabelParagraph.setStyle("Heading2"); XWPFRun runDatasetTitle1 = datasetLabelParagraph.createRun(); runDatasetTitle1.setText("Title: "); runDatasetTitle1.setBold(true); runDatasetTitle1.setFontSize(12); XWPFRun runDatasetTitle = datasetLabelParagraph.createRun(); runDatasetTitle.setText(datasetEntity.getLabel()); runDatasetTitle.setColor("2E75B6"); runDatasetTitle.setBold(true); runDatasetTitle.setFontSize(12); XWPFParagraph datasetTemplateParagraph = document.createParagraph(); datasetTemplateParagraph.setStyle("Heading3"); XWPFRun runDatasetTemplate1 = datasetTemplateParagraph.createRun(); runDatasetTemplate1.setText("Template: "); runDatasetTemplate1.setBold(true); runDatasetTemplate1.setFontSize(12); XWPFRun runDatasetTemplate = datasetTemplateParagraph.createRun(); runDatasetTemplate.setText(datasetEntity.getProfile().getLabel()); runDatasetTemplate.setColor("2E75B6"); runDatasetTemplate.setBold(true); runDatasetTemplate.setFontSize(12); XWPFParagraph externalReferencesParagraph = document.createParagraph(); externalReferencesParagraph.setStyle("Heading3"); XWPFRun externalReferencesRun = externalReferencesParagraph.createRun(); externalReferencesRun.setText("External References"); externalReferencesRun.setColor("2E75B6"); externalReferencesRun.setBold(true); externalReferencesRun.setFontSize(12); wordBuilder.addParagraphContent("Data Repositories", document, ParagraphStyle.HEADER4, BigInteger.ZERO); if (datasetEntity.getDatasetDataRepositories().size() > 0) { wordBuilder.addParagraphContent(datasetEntity.getDatasetDataRepositories().stream().map(DatasetDataRepository::getDataRepository).map(DataRepository::getLabel).collect(Collectors.joining(", ")) , document, ParagraphStyle.TEXT, BigInteger.ZERO); } wordBuilder.addParagraphContent("External Datasets", document, ParagraphStyle.HEADER4, BigInteger.ZERO); if (datasetEntity.getDatasetExternalDatasets().size() > 0) { wordBuilder.addParagraphContent(datasetEntity.getDatasetExternalDatasets().stream().map(DatasetExternalDataset::getExternalDataset).map(ExternalDataset::getLabel).collect(Collectors.joining(", ")) , document, ParagraphStyle.TEXT, BigInteger.ZERO); } wordBuilder.addParagraphContent("Registries", document, ParagraphStyle.HEADER4, BigInteger.ZERO); if (datasetEntity.getRegistries().size() > 0) { wordBuilder.addParagraphContent(datasetEntity.getRegistries().stream().map(Registry::getLabel).collect(Collectors.joining(", ")) , document, ParagraphStyle.TEXT, BigInteger.ZERO); } wordBuilder.addParagraphContent("Services", document, ParagraphStyle.HEADER4, BigInteger.ZERO); if (datasetEntity.getServices().size() > 0) { wordBuilder.addParagraphContent(datasetEntity.getServices().stream().map(DatasetService::getService).map(Service::getLabel).collect(Collectors.joining(", ")) , document, ParagraphStyle.TEXT, BigInteger.ZERO); } /*wordBuilder.addParagraphContent("Tags", document, ParagraphStyle.HEADER3, BigInteger.ZERO); if (datasetEntity.().size() > 0) { wordBuilder.addParagraphContent(datasetEntity.getServices().stream().map(DatasetService::getService).map(Service::getLabel).collect(Collectors.joining(", ")) , document, ParagraphStyle.HEADER4, BigInteger.ZERO); }*/ wordBuilder.addParagraphContent(datasetEntity.getDescription(), document, ParagraphStyle.TEXT, BigInteger.ZERO); // Dataset Description custom style. XWPFParagraph datasetDescriptionParagraph = document.createParagraph(); datasetDescriptionParagraph.setStyle("Heading3"); XWPFRun datasetDescriptionRun = datasetDescriptionParagraph.createRun(); datasetDescriptionRun.setText("Dataset Description"); datasetDescriptionRun.setColor("2E75B6"); datasetDescriptionRun.setBold(true); datasetDescriptionRun.setFontSize(12); PagedDatasetProfile pagedDatasetProfile = datasetManager.getPagedProfile(dataset, datasetEntity); visibilityRuleService.setProperties(properties); visibilityRuleService.buildVisibilityContext(pagedDatasetProfile.getRules()); try { wordBuilder.build(document, pagedDatasetProfile, visibilityRuleService); } catch (IOException e) { logger.error(e.getMessage(), e); } // Page break at the end of the Dataset. XWPFParagraph parBreakDataset = document.createParagraph(); }); // Removes the top empty headings. for (int i = 0; i < 6; i++) { document.removeBodyElement(0); } String fileName = ""; if (versioned) { fileName = dmpEntity.getLabel() + " v" + dmpEntity.getVersion(); } else { fileName = dmpEntity.getLabel(); } fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); File exportFile = new File(fileName + ".docx"); FileOutputStream out = new FileOutputStream(exportFile); document.write(out); out.close(); return exportFile; } /*public File getPdfDocument(String id) throws InstantiationException, IllegalAccessException, InterruptedException, IOException { File file = this.getWordDocument(id); String fileName = file.getName(); if (fileName.endsWith(".docx")){ fileName = fileName.substring(0, fileName.length() - 5); } return this.datasetManager.convertToPDF(file, environment, fileName); }*/ public eu.eudat.models.data.dmp.DataManagementPlan getSingle(String id, Principal principal) { DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (dataManagementPlanEntity.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) { if (!dataManagementPlanEntity.isPublic()) { throw new UnauthorisedException(); } } eu.eudat.models.data.dmp.DataManagementPlan dataManagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); dataManagementPlan.fromDataModel(dataManagementPlanEntity); Map dmpProperties = dataManagementPlanEntity.getDmpProperties() != null ? new org.json.JSONObject(dataManagementPlanEntity.getDmpProperties()).toMap() : null; if (dmpProperties != null && dataManagementPlan.getDynamicFields() != null) dataManagementPlan.getDynamicFields().forEach(item -> { Map properties = (Map) dmpProperties.get(item.getId()); if (properties != null) item.setValue(new Tuple<>(properties.get("id"), properties.get("label"))); }); return dataManagementPlan; } public DataManagementPlanOverviewModel getOverviewSingle(String id, Principal principal) throws Exception { DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (dataManagementPlanEntity.getStatus() == DMP.DMPStatus.DELETED.getValue()) { throw new Exception("DMP is deleted."); } if (dataManagementPlanEntity.getUsers() .stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()) .collect(Collectors.toList()).size() == 0) throw new UnauthorisedException(); DataManagementPlanOverviewModel datamanagementPlan = new DataManagementPlanOverviewModel(); datamanagementPlan.fromDataModelDatasets(dataManagementPlanEntity); return datamanagementPlan; } public eu.eudat.models.data.dmp.DataManagementPlan getSinglePublic(String id, DynamicGrantConfiguration dynamicGrantConfiguration) throws Exception { DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (dataManagementPlanEntity != null && dataManagementPlanEntity.getStatus() == 1) { eu.eudat.models.data.dmp.DataManagementPlan datamanagementPlan = new eu.eudat.models.data.dmp.DataManagementPlan(); datamanagementPlan.fromDataModel(dataManagementPlanEntity); datamanagementPlan.setDatasets(datamanagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); Map dmpProperties = dataManagementPlanEntity.getDmpProperties() != null ? new org.json.JSONObject(dataManagementPlanEntity.getDmpProperties()).toMap() : null; // datamanagementPlan.setDynamicFields(dynamicGrantConfiguration.getFields().stream().map(item -> { // DynamicFieldWithValue fieldWithValue = new DynamicFieldWithValue(); // fieldWithValue.setId(item.getId()); // fieldWithValue.setDependencies(item.getDependencies()); // fieldWithValue.setName(item.getName()); // fieldWithValue.setQueryProperty(item.getQueryProperty()); // fieldWithValue.setRequired(item.getRequired()); // return fieldWithValue; // }).collect(Collectors.toList())); if (dmpProperties != null && datamanagementPlan.getDynamicFields() != null) datamanagementPlan.getDynamicFields().forEach(item -> { Map properties = (Map) dmpProperties.get(item.getId()); if (properties != null) item.setValue(new Tuple<>(properties.get("id"), properties.get("label"))); }); return datamanagementPlan; } else { throw new Exception("Selected DMP is not public"); } } public DataManagementPlanOverviewModel getOverviewSinglePublic(String id) throws Exception { DMP dataManagementPlanEntity = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (dataManagementPlanEntity != null && dataManagementPlanEntity.getStatus() == 1) { DataManagementPlanOverviewModel datamanagementPlan = new DataManagementPlanOverviewModel(); datamanagementPlan.fromDataModelDatasets(dataManagementPlanEntity); datamanagementPlan.setDatasets(datamanagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); return datamanagementPlan; } else { throw new Exception("Selected DMP is not public"); } } public List getWithCriteria(DMPDao dmpsRepository, DataManagementPlanCriteriaRequest dataManagementPlanCriteria, Principal principal) throws IllegalAccessException, InstantiationException { UUID principalID = principal.getId(); QueryableList items = dmpsRepository.getWithCriteria(dataManagementPlanCriteria.getCriteria()).withHint(HintedModelFactory.getHint(DataManagementPlan.class)); List roles = new LinkedList<>(); QueryableList authenticatedItems = dmpsRepository.getAuthenticated(items, principalID, roles); List datamanagementPlans = authenticatedItems.select(item -> new DataManagementPlan().fromDataModel(item)); return datamanagementPlans; } public List> getDynamicFields(String id, DynamicGrantConfiguration dynamicGrantConfiguration, DynamicFieldsCriteria criteria) throws IllegalAccessException, InstantiationException { List> result = new LinkedList<>(); RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity<>("parameters", headers); Property property = dynamicGrantConfiguration.getConfiguration().getConfigurationProperties().stream() .filter(item -> item.getId().equals(id)).findFirst().orElse(null); StringBuilder stringBuilder = new StringBuilder(); if (criteria.getLike() != null) stringBuilder.append("?search=" + criteria.getLike()); if (property.getDependencies() != null && !property.getDependencies().isEmpty() && criteria.getDynamicFields() != null && !criteria.getDynamicFields().isEmpty()) { property.getDependencies().stream().forEach(item -> { DynamicFieldsCriteria.DynamicFieldDependencyCriteria dependencyCriteria = criteria.getDynamicFields().stream().filter(dfield -> dfield.getProperty().equals(item.getId())) .findFirst().orElse(null); if (dependencyCriteria != null) { if (criteria.getLike() != null || property.getDependencies().indexOf(item) > 0) stringBuilder.append("&"); stringBuilder.append(item.getQueryProperty() + "=" + dependencyCriteria.getValue()); } }); ResponseEntity response = restTemplate.exchange(property.getSourceUrl() + stringBuilder.toString(), HttpMethod.GET, entity, ArrayList.class); response.getBody().forEach(item -> { Tuple tuple = new Tuple<>(); tuple.setId((String) (((Map) item).get(property.getExternalFieldId()))); tuple.setLabel((String) (((Map) item).get(property.getExternalFieldLabel()))); result.add(tuple); }); } else { ResponseEntity response = restTemplate.exchange(property.getSourceUrl() + stringBuilder.toString(), HttpMethod.GET, entity, ArrayList.class); response.getBody().forEach(item -> { Tuple tuple = new Tuple<>(); tuple.setId((String) (((Map) item).get(property.getExternalFieldId()))); tuple.setLabel((String) (((Map) item).get(property.getExternalFieldLabel()))); result.add(tuple); }); } return result; } public DMP createOrUpdate(ApiContext apiContext, DataManagementPlanEditorModel dataManagementPlan, Principal principal) throws Exception { boolean setNotification = false; if (dataManagementPlan.getId() != null) { DMP dmp1 = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(dataManagementPlan.getId()); if (!isUserOwnerOfDmp(dmp1, principal)) { throw new Exception("User not being the creator is not authorized to edit this DMP."); } if (dmp1.getModified().getTime() != dataManagementPlan.getModified().getTime()) { throw new Exception("Another user have already edit that DMP."); } List datasetList = new ArrayList<>(dmp1.getDataset()); for (Dataset dataset : datasetList) { if (dataManagementPlan.getProfiles().stream().filter(associatedProfile -> dataset.getProfile().getId().equals(associatedProfile.getId())).findAny().orElse(null) == null) throw new Exception("Dataset Template for Dataset Description is missing from the DMP."); } if (dataManagementPlan.getStatus() == (int) DMP.DMPStatus.FINALISED.getValue() && dmp1.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) throw new Exception("DMP is finalized, therefore cannot be edited."); setNotification = true; } DMP newDmp = dataManagementPlan.toDataModel(); if (newDmp.getStatus() == (int) DMP.DMPStatus.FINALISED.getValue()) { checkDmpValidationRules(newDmp); } UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); createOrganisationsIfTheyDontExist(newDmp, apiContext.getOperationsContext().getDatabaseRepository().getOrganisationDao()); createResearchersIfTheyDontExist(newDmp, apiContext.getOperationsContext().getDatabaseRepository().getResearcherDao(), user); createFunderIfItDoesntExist(newDmp, apiContext.getOperationsContext().getDatabaseRepository().getFunderDao()); createGrantIfItDoesntExist(newDmp, apiContext.getOperationsContext().getDatabaseRepository().getGrantDao()); if (newDmp.getProject().getLabel() == null || newDmp.getProject().getLabel().trim().isEmpty()) { newDmp.setProject(newDmp.getProject().projectFromGrant(newDmp.getGrant())); } createProjectIfItDoesntExist(newDmp, apiContext.getOperationsContext().getDatabaseRepository().getProjectDao()); DMP dmp; if (dataManagementPlan.getId() != null) { dmp = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(dataManagementPlan.getId()); } else dmp = new DMP(); newDmp.setCreated(dmp.getCreated() == null ? new Date() : dmp.getCreated()); if (newDmp.getUsers()!= null && newDmp.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()) .collect(Collectors.toList()).size() == 0) { List userDMPList = new ArrayList<>(newDmp.getUsers()); for (UserInfoListingModel userInfoListingModel : dataManagementPlan.getUsers()) { for (UserDMP userDMP : userDMPList) { if (!(userDMP.getUser().getId().equals(userInfoListingModel.getId()))) { apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().delete(userDMP); } } } } checkIfUserCanEditGrant(newDmp, user); assignGrandUserIfInternal(newDmp, user); assignFunderUserIfInternal(newDmp, user); assignProjectUserIfInternal(newDmp, user); apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().createOrUpdate(newDmp.getGrant()); newDmp = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(newDmp); // Dataset manipulation for when the DMP is set to be finalized. if (dataManagementPlan.getStatus() == DMP.DMPStatus.FINALISED.getValue()) { if (dataManagementPlan.getDatasetsToBeFinalized() != null && !dataManagementPlan.getDatasetsToBeFinalized().isEmpty()) { apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(dataManagementPlan.getDatasetsToBeFinalized())) .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); List datasetsToBeCanceled = new LinkedList<>(); for (DatasetListingModel dataset : dataManagementPlan.getDatasets()) { if (!(dataset.getStatus() == (int) Dataset.Status.FINALISED.getValue()) && !dataManagementPlan.getDatasetsToBeFinalized().contains(UUID.fromString(dataset.getId()))) { datasetsToBeCanceled.add(UUID.fromString(dataset.getId())); } } if (!datasetsToBeCanceled.isEmpty()) apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); } else { List datasetsToBeCanceled = new LinkedList<>(); for (DatasetListingModel dataset : dataManagementPlan.getDatasets()) { if (!(dataset.getStatus() == (int) Dataset.Status.FINALISED.getValue())) { datasetsToBeCanceled.add(UUID.fromString(dataset.getId())); } } if (!datasetsToBeCanceled.isEmpty()) apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); } } if (dataManagementPlan.getAssociatedUsers().size() == 0) assignUser(newDmp, user); if (setNotification) { if (newDmp.getStatus() != DMP.DMPStatus.FINALISED.getValue()) { this.sendNotification(newDmp, user, NotificationType.DMP_MODIFIED); } else { this.sendNotification(newDmp, user, NotificationType.DMP_MODIFIED_FINALISED); } } return newDmp; } private void sendNotification(DMP dmp, UserInfo user, NotificationType notificationType) { List userDMPS = databaseRepository.getUserDmpDao().asQueryable().where(((builder, root) -> builder.equal(root.get("dmp").get("id"), dmp.getId()))).toList(); for (UserDMP userDMP : userDMPS) { if (!userDMP.getUser().getId().equals(user.getId())) { Notification notification = new Notification(); notification.setUserId(user); notification.setType(notificationType); notification.setNotifyState(NotifyState.PENDING); notification.setIsActive(ActiveStatus.ACTIVE); notification.setData("{" + "\"userId\": \"" + userDMP.getUser().getId() + "\"" + ", \"id\": \"" + userDMP.getDmp().getId() + "\"" + ", \"name\": \"" + userDMP.getDmp().getLabel() + "\"" + ", \"path\": \"" + notificationPaths.get(notificationType) +"\"" + "}"); notification.setCreatedAt(new Date()); notification.setUpdatedAt(notification.getCreatedAt()); notification.setContactTypeHint(ContactType.EMAIL); notification.setContactHint(userDMP.getUser().getEmail()); databaseRepository.getNotificationDao().createOrUpdate(notification); } } } private void assignUser(DMP dmp, UserInfo userInfo) { UserDMP userDMP = new UserDMP(); userDMP.setDmp(dmp); userDMP.setUser(userInfo); userDMP.setRole(UserDMP.UserDMPRoles.OWNER.getValue()); databaseRepository.getUserDmpDao().createOrUpdate(userDMP); } public void newVersion(UUID uuid, DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { DMP oldDmp = databaseRepository.getDmpDao().find(uuid); if (!isUserOwnerOfDmp(oldDmp, principal)) { throw new Exception("User not being the creator is not authorized to perform this action."); } DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); LinkedList list = new LinkedList<>(); list.push(oldDmp.getGroupId()); criteria.setGroupIds(list); criteria.setAllVersions(false); QueryableList dataManagementPlanQueryableList = databaseRepository.getDmpDao().getWithCriteria(criteria); List latestVersionDMP = dataManagementPlanQueryableList.toList(); if (latestVersionDMP.get(0).getVersion().equals(oldDmp.getVersion())) { DMP newDmp = dataManagementPlan.toDataModel(); UserInfo user = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build(); createOrganisationsIfTheyDontExist(newDmp, databaseRepository.getOrganisationDao()); createResearchersIfTheyDontExist(newDmp, databaseRepository.getResearcherDao(), user); createFunderIfItDoesntExist(newDmp, databaseRepository.getFunderDao()); createGrantIfItDoesntExist(newDmp, databaseRepository.getGrantDao()); if (newDmp.getProject().getLabel() == null || newDmp.getProject().getLabel().trim().isEmpty()) { newDmp.setProject(newDmp.getProject().projectFromGrant(newDmp.getGrant())); } createProjectIfItDoesntExist(newDmp, databaseRepository.getProjectDao()); newDmp.setGroupId(oldDmp.getGroupId()); newDmp.setVersion(oldDmp.getVersion() + 1); newDmp.setId(null); checkIfUserCanEditGrant(newDmp, user); assignGrandUserIfInternal(newDmp, user); assignFunderUserIfInternal(newDmp, user); assignProjectUserIfInternal(newDmp, user); databaseRepository.getGrantDao().createOrUpdate(newDmp.getGrant()); newDmp = databaseRepository.getDmpDao().createOrUpdate(newDmp); // Assign creator. assignUser(newDmp, user); copyDatasets(newDmp, databaseRepository.getDatasetDao()); } else { throw new DMPNewVersionException("Version to update not the latest."); } } public void clone(DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { DMP newDmp = dataManagementPlan.toDataModel(); UserInfo user = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build(); createOrganisationsIfTheyDontExist(newDmp, databaseRepository.getOrganisationDao()); createResearchersIfTheyDontExist(newDmp, databaseRepository.getResearcherDao(), user); createFunderIfItDoesntExist(newDmp, databaseRepository.getFunderDao()); createGrantIfItDoesntExist(newDmp, databaseRepository.getGrantDao()); if (newDmp.getProject().getLabel() == null || newDmp.getProject().getLabel().trim().isEmpty()) { newDmp.setProject(newDmp.getProject().projectFromGrant(newDmp.getGrant())); } createProjectIfItDoesntExist(newDmp, databaseRepository.getProjectDao()); newDmp.setGroupId(UUID.randomUUID()); newDmp.setVersion(0); newDmp.setId(null); checkIfUserCanEditGrant(newDmp, user); assignGrandUserIfInternal(newDmp, user); assignFunderUserIfInternal(newDmp, user); assignProjectUserIfInternal(newDmp, user); databaseRepository.getGrantDao().createOrUpdate(newDmp.getGrant()); newDmp = databaseRepository.getDmpDao().createOrUpdate(newDmp); assignUser(newDmp, user); copyDatasets(newDmp, databaseRepository.getDatasetDao()); } public void delete(UUID uuid) throws DMPWithDatasetsDeleteException { DatasetCriteria criteria = new DatasetCriteria(); List dmpIds = Collections.singletonList(uuid); criteria.setDmpIds(dmpIds); if (apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().getWithCriteria(criteria).toList().size() > 0) throw new DMPWithDatasetsDeleteException("You cannot Remove Datamanagement Plan with Datasets"); DMP oldDmp = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(uuid); oldDmp.setStatus(DMP.DMPStatus.DELETED.getValue()); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(oldDmp); } private void createResearchersIfTheyDontExist(DMP newDmp, ResearcherDao researcherRepository, UserInfo user) { if (newDmp.getResearchers() != null && !newDmp.getResearchers().isEmpty()) { for (eu.eudat.data.entities.Researcher researcher : newDmp.getResearchers()) { ResearcherCriteria criteria = new ResearcherCriteria(); criteria.setLike(researcher.getReference()); List entries = researcherRepository.getWithCriteria(criteria).toList(); if (entries != null && !entries.isEmpty()) researcher.setId(entries.get(0).getId()); else { researcher.setCreationUser(user); researcherRepository.createOrUpdate(researcher); } } } } private void createOrganisationsIfTheyDontExist(DMP newDmp, OrganisationDao organisationRepository) { if (newDmp.getOrganisations() != null && !newDmp.getOrganisations().isEmpty()) { for (eu.eudat.data.entities.Organisation organisation : newDmp.getOrganisations()) { OrganisationCriteria criteria = new OrganisationCriteria(); criteria.setLike(organisation.getReference()); List entries = organisationRepository.getWithCriteria(criteria).toList(); if (entries != null && !entries.isEmpty()) organisation.setId(entries.get(0).getId()); else organisationRepository.createOrUpdate(organisation); } } } private void createGrantIfItDoesntExist(DMP newDmp, GrantDao grantDao) { if (newDmp.getGrant() != null) { Grant grant = newDmp.getGrant(); GrantCriteria criteria = new GrantCriteria(); if (grant.getReference() != null) { criteria.setReference(grant.getReference()); eu.eudat.data.entities.Grant grantEntity = grantDao.getWithCriteria(criteria).getSingleOrDefault(); if (grantEntity != null) grant.setId(grantEntity.getId()); else { grant.setType(Grant.GrantType.EXTERNAL.getValue()); grant.setCreationUser(null); grantDao.createOrUpdate(grant); } } else { grant.setType(Grant.GrantType.EXTERNAL.getValue()); grant.setCreationUser(null); grantDao.createOrUpdate(grant); } } } private void createFunderIfItDoesntExist(DMP newDmp, FunderDao funderDao) { if (newDmp.getGrant().getFunder() != null) { Funder funder = newDmp.getGrant().getFunder(); FunderCriteria criteria = new FunderCriteria(); if (funder.getReference() != null) { criteria.setReference(funder.getReference()); eu.eudat.data.entities.Funder funderEntity = funderDao.getWithCritetia(criteria).getSingleOrDefault(); if (funderEntity != null) funder.setId(funderEntity.getId()); else { funderDao.createOrUpdate(funder); } } else { funderDao.createOrUpdate(funder); } } } private void createProjectIfItDoesntExist(DMP newDmp, ProjectDao projectDao) { if (newDmp.getProject() != null) { Project project = newDmp.getProject(); ProjectCriteria criteria = new ProjectCriteria(); if (project.getReference() != null) { criteria.setReference(project.getReference()); eu.eudat.data.entities.Project projectEntity = projectDao.getWithCritetia(criteria).getSingleOrDefault(); if (projectEntity != null) project.setId(projectEntity.getId()); else { project.setType(Project.ProjectType.EXTERNAL.getValue()); if (project.getId() == null) project.setId(UUID.randomUUID()); projectDao.createOrUpdate(project); } } else { project.setType(Project.ProjectType.EXTERNAL.getValue()); if (project.getId() == null) project.setId(UUID.randomUUID()); projectDao.createOrUpdate(project); } } } private void checkIfUserCanEditGrant(DMP dmp, UserInfo user) throws Exception{ if (dmp.getGrant().getId() != null) { Grant grant = apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().find(dmp.getGrant().getId()); if (grant.getFunder() != null && dmp.getGrant().getFunder() != null && !grant.getFunder().getId().equals(dmp.getGrant().getFunder().getId())) { if (grant.getCreationUser() == null) { throw new Exception("Grant has no user, therefore, cannot be edited."); } if (!grant.getCreationUser().getId().equals(user.getId())) { throw new Exception("User is not the owner of the Grant, therefore, cannot edit it."); } } } } private void checkDmpValidationRules(DMP dmp) throws Exception { if (dmp.getLabel() == null || dmp.getLabel().trim().isEmpty()) { throw new Exception("DMP has no label."); } if (dmp.getAssociatedDmps().size() == 0) { throw new Exception("DMP does not contain Dataset Templates."); } if (dmp.getGrant() == null) { throw new Exception("DMP has no Grant assigned."); } } private void assignGrandUserIfInternal(DMP dmp, UserInfo user) { if (dmp.getGrant().getCreationUser() == null && (dmp.getGrant().getReference() != null && dmp.getGrant().getReference().startsWith("dmp:"))) { dmp.getGrant().setCreationUser(user); } } private void assignFunderUserIfInternal(DMP dmp, UserInfo user) { if (dmp.getGrant().getFunder().getCreationUser() == null && ( dmp.getGrant().getFunder().getReference() != null && dmp.getGrant().getFunder().getReference().startsWith("dmp:"))) { dmp.getGrant().getFunder().setCreationUser(user); } } private void assignProjectUserIfInternal(DMP dmp, UserInfo user) { if (dmp.getProject().getCreationUser() == null && (dmp.getProject().getReference() != null && dmp.getProject().getReference().startsWith("dmp:"))) { dmp.getProject().setCreationUser(user); } } private void copyDatasets(DMP newDmp, DatasetDao datasetDao) { List> futures = new LinkedList<>(); for (Dataset dataset : newDmp.getDataset()) { datasetDao.asQueryable().withHint(HintedModelFactory.getHint(DatasetListingModel.class)).where((builder, root) -> builder.equal(root.get("id"), dataset.getId())).getSingleAsync() .thenApplyAsync(entityDataset -> { Dataset newDataset = new Dataset(); try { this.datasetManager.updateTags(apiContext.getOperationsContext().getDatasetRepository(), new DatasetWizardModel().fromDataModel(entityDataset)); } catch (IOException e) { logger.error(e.getMessage(), e); } newDataset.update(entityDataset); newDataset.setDmp(newDmp); newDataset.setStatus(Dataset.Status.SAVED.getValue()); if (newDataset.getDatasetDataRepositories() != null) { newDataset.setDatasetDataRepositories(newDataset.getDatasetDataRepositories().stream().map(item -> { DataRepository dataRepository = new DataRepository(); dataRepository.setId(item.getDataRepository().getId()); DatasetDataRepository datasetDataRepository = new DatasetDataRepository(); datasetDataRepository.setDataRepository(dataRepository); datasetDataRepository.setDataset(newDataset); datasetDataRepository.setData(item.getData()); return datasetDataRepository; }).collect(Collectors.toSet())); } if (newDataset.getDatasetExternalDatasets() != null) { newDataset.setDatasetExternalDatasets(newDataset.getDatasetExternalDatasets().stream().map(item -> { ExternalDataset externalDataset = new ExternalDataset(); externalDataset.setId(item.getExternalDataset().getId()); DatasetExternalDataset datasetExternalDataset = new DatasetExternalDataset(); datasetExternalDataset.setExternalDataset(externalDataset); datasetExternalDataset.setDataset(newDataset); datasetExternalDataset.setData(item.getData()); return datasetExternalDataset; }).collect(Collectors.toSet())); } if (newDataset.getRegistries() != null) { newDataset.setRegistries(newDataset.getRegistries().stream().map(item -> { Registry registry = new Registry(); registry.setId(item.getId()); return registry; }).collect(Collectors.toSet())); } if (newDataset.getServices() != null) { newDataset.setServices(newDataset.getServices().stream().map(item -> { Service service = new Service(); service.setId(item.getId()); DatasetService datasetService = new DatasetService(); datasetService.setService(service); datasetService.setDataset(newDataset); datasetService.setData(item.getData()); return datasetService; }).collect(Collectors.toSet())); } newDataset.setCreated(new Date()); return newDataset; }).thenApplyAsync(item -> { futures.add(datasetDao.createOrUpdateAsync(item)); return futures; }).join(); DatasetCriteria criteria = new DatasetCriteria(); criteria.setDmpIds(Collections.singletonList(newDmp.getId())); datasetDao.getWithCriteria(criteria).toList().stream().max(Comparator.comparing(Dataset::getCreated)).ifPresent(dataset1 -> { try { datasetManager.updateTags(apiContext.getOperationsContext().getDatasetRepository(), new DatasetWizardModel().fromDataModel(dataset1)); } catch (IOException e) { logger.error(e.getMessage(), e); } }); } } private FileEnvelope getXmlDocument(String id, Principal principal) throws InstantiationException, IllegalAccessException, IOException { ExportXmlBuilder xmlBuilder = new ExportXmlBuilder(); VisibilityRuleService visibilityRuleService = utilitiesService.getVisibilityRuleService(); eu.eudat.data.entities.DMP dmp = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (!dmp.isPublic() && dmp.getUsers().stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()).collect(Collectors.toList()).size() == 0) throw new UnauthorisedException(); List datasets = dmp.getDataset().stream().collect(Collectors.toList()); String fileName = dmp.getLabel(); fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); File xmlFile = new File(fileName + ".xml"); BufferedWriter writer = new BufferedWriter(new FileWriter(xmlFile, true)); Document xmlDoc = XmlBuilder.getDocument(); Element dmpElement = xmlDoc.createElement("dmp"); Element dmpDescription = xmlDoc.createElement("description"); dmpDescription.setTextContent(dmp.getDescription()); dmpElement.appendChild(dmpDescription); Element dmpName = xmlDoc.createElement("dmpName"); dmpName.setTextContent(dmp.getLabel()); dmpElement.appendChild(dmpName); DMPProfile dmpProfile = dmp.getProfile(); Element dmpProfileElement = xmlDoc.createElement("dmpProfile"); Element dmpProfileName = xmlDoc.createElement("dmpProfileName"); if (!(dmpProfile == null)) { dmpProfileName.setTextContent(dmpProfile.getLabel()); dmpProfileElement.appendChild(dmpProfileName); Element dmpProfileId = xmlDoc.createElement("dmpProfileId"); dmpProfileId.setTextContent(dmpProfile.getId().toString()); dmpProfileElement.appendChild(dmpProfileId); Element values = xmlDoc.createElement("values"); values.setTextContent(dmpProfile.getDefinition()); dmpProfileElement.appendChild(values); } dmpElement.appendChild(dmpProfileElement); // Funder. Element funder = xmlDoc.createElement("funder"); Element funderLabel = xmlDoc.createElement("label"); Element funderId = xmlDoc.createElement("id"); funderLabel.setTextContent(dmp.getGrant().getFunder().getLabel()); funderId.setTextContent(dmp.getGrant().getFunder().getId().toString()); funder.appendChild(funderLabel); funder.appendChild(funderId); dmpElement.appendChild(funder); // Grant. Element grant = xmlDoc.createElement("grant"); Element grantLabel = xmlDoc.createElement("label"); Element grantId = xmlDoc.createElement("id"); grantLabel.setTextContent(dmp.getGrant().getLabel()); grantId.setTextContent(dmp.getGrant().getId().toString()); grant.appendChild(grantLabel); grant.appendChild(grantId); dmpElement.appendChild(grant); // Project. Element project = xmlDoc.createElement("project"); Element projectLabel = xmlDoc.createElement("label"); Element projectId = xmlDoc.createElement("id"); projectLabel.setTextContent(dmp.getProject().getLabel()); projectId.setTextContent(dmp.getProject().getId().toString()); project.appendChild(projectLabel); project.appendChild(projectId); dmpElement.appendChild(project); Element organisationsElement = xmlDoc.createElement("organisations"); for (Organisation organisation : dmp.getOrganisations()) { Element organisationElement = xmlDoc.createElement("organisation"); Element organisationNameElement = xmlDoc.createElement("name"); organisationNameElement.setTextContent(organisation.getLabel()); Element organisationReferenceElement = xmlDoc.createElement("reference"); organisationReferenceElement.setTextContent(organisation.getReference()); organisationElement.appendChild(organisationNameElement); organisationElement.appendChild(organisationReferenceElement); organisationsElement.appendChild(organisationElement); } dmpElement.appendChild(organisationsElement); Element researchersElement = xmlDoc.createElement("researchers"); for (Researcher researcher : dmp.getResearchers()) { Element researcherElement = xmlDoc.createElement("researcher"); Element researcherNameElement = xmlDoc.createElement("name"); researcherNameElement.setTextContent(researcher.getLabel()); Element researcherReferenceElement = xmlDoc.createElement("reference"); researcherReferenceElement.setTextContent(researcher.getReference()); researcherElement.appendChild(researcherNameElement); researcherElement.appendChild(researcherReferenceElement); researchersElement.appendChild(researcherElement); } dmpElement.appendChild(researchersElement); Element datasetsElement = xmlDoc.createElement("datasets"); for (Dataset dataset : datasets) { Element datasetElement = xmlDoc.createElement("dataset"); Element datsetProfileElement = xmlDoc.createElement("profile"); datasetElement.setAttribute("name", dataset.getLabel()); datasetElement.appendChild(datsetProfileElement); datsetProfileElement.setTextContent(dataset.getProfile().getId().toString()); DatasetWizardModel datasetWizardModel = new DatasetWizardModel(); Map properties = new HashMap<>(); if (dataset.getProperties() != null) { JSONObject jobject = new JSONObject(dataset.getProperties()); properties = jobject.toMap(); } PagedDatasetProfile pagedDatasetProfile = datasetManager.getPagedProfile(datasetWizardModel, dataset); visibilityRuleService.setProperties(properties); visibilityRuleService.buildVisibilityContext(pagedDatasetProfile.getRules()); datasetElement.appendChild(xmlBuilder.createPages(pagedDatasetProfile.getPages(), visibilityRuleService, xmlDoc)); datasetsElement.appendChild(datasetElement); } Element profiles = xmlDoc.createElement("profiles"); // Get DatasetProfiles from DMP to add to XML. for (DatasetProfile datasetProfile : dmp.getAssociatedDmps()) { Element profile = xmlDoc.createElement("profile"); Element profileLabel = xmlDoc.createElement("profilelabel"); profileLabel.setTextContent(datasetProfile.getLabel()); profile.appendChild(profileLabel); Element profileId = xmlDoc.createElement("profileId"); profileId.setTextContent(datasetProfile.getId().toString()); profile.appendChild(profileId); profiles.appendChild(profile); } dmpElement.appendChild(profiles); dmpElement.appendChild(datasetsElement); xmlDoc.appendChild(dmpElement); String xml = XmlBuilder.generateXml(xmlDoc); writer.write(xml); writer.close(); FileEnvelope fileEnvelope = new FileEnvelope(); fileEnvelope.setFile(xmlFile); fileEnvelope.setFilename(dmp.getLabel()); return fileEnvelope; } public ResponseEntity getRDAJsonDocument(String id, DatasetManager datasetManager, Principal principal) throws IOException { eu.eudat.data.entities.DMP dmp = databaseRepository.getDmpDao().find(UUID.fromString(id)); if (!dmp.isPublic() && dmp.getUsers().stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) throw new UnauthorisedException(); RDAExportModel rdaExportModel = new RDAExportModel().fromDataModel(dmp, datasetManager, principal); ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); String fileName = dmp.getLabel(); fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); File file = new File(fileName); try { mapper.writeValue(file, rdaExportModel); } catch (IOException e) { logger.error(e.getMessage(), e); } InputStream resource = new FileInputStream(file); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentLength(file.length()); responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); responseHeaders.set("Content-Disposition", "attachment;filename=" + file.getName()); responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); byte[] content = org.apache.poi.util.IOUtils.toByteArray(resource); resource.close(); Files.deleteIfExists(file.toPath()); return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK); } public ResponseEntity getDocument(String id, String contentType, Principal principal, ConfigLoader configLoader) throws InstantiationException, IllegalAccessException, IOException { File file; switch (contentType) { case "application/xml": file = getXmlDocument(id, principal).getFile(); break; case "application/msword": file = getWordDocument(id, principal, configLoader); break; default: file = getXmlDocument(id, principal).getFile(); } InputStream resource = new FileInputStream(file); HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setContentLength(file.length()); responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); responseHeaders.set("Content-Disposition", "attachment;filename=" + file.getName()); responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); byte[] content = org.apache.poi.util.IOUtils.toByteArray(resource); resource.close(); Files.deleteIfExists(file.toPath()); return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK); } public List createDmpFromXml(ApiContext apiContext, MultipartFile[] files, Principal principal) throws IOException, JAXBException, Exception { List dataManagementPlans = new ArrayList<>(); // Jaxb approach. JAXBContext jaxbContext; for (MultipartFile multipartFile : Arrays.asList(files)) { // Gets one item from the array. try { InputStream in = multipartFile.getInputStream(); // Transforms item to InputStream. jaxbContext = JAXBContext.newInstance(DmpImportModel.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); DmpImportModel dmpImportModel = (DmpImportModel) jaxbUnmarshaller.unmarshal(in); dataManagementPlans.add(dmpImportModel); } catch (IOException | JAXBException ex) { logger.error(ex.getMessage(), ex); } // TODO Iterate through the list of dataManagementPlans. // Creates new dataManagementPlan to fill it with the data model that was parsed from the xml. // Creates properties. DataManagementPlanEditorModel dm = new DataManagementPlanEditorModel(); DataManagementPlanProfile dmpProfile = new DataManagementPlanProfile(); List fieldList = new LinkedList<>(); Field field = new Field(); field.setLabel(dataManagementPlans.get(0).getDmpProfile().getDmpProfileName()); field.setId(dataManagementPlans.get(0).getDmpProfile().getDmpProfileId()); fieldList.add(field); dmpProfile.setFields(fieldList); /*Tuple tuple = new Tuple(); tuple.setId(dataManagementPlans.get(0).getDmpProfile().getDmpProfileId()); tuple.setLabel(dataManagementPlans.get(0).getDmpProfile().getDmpProfileName());*/ eu.eudat.models.data.funder.Funder funder = new eu.eudat.models.data.funder.Funder(); FunderImportModels funderImport = dataManagementPlans.get(0).getFunderImportModels(); funder.setId(funderImport.getId()); funder.setLabel(funderImport.getLabel()); FunderDMPEditorModel funderEditor = new FunderDMPEditorModel(); funderEditor.setExistFunder(funder); eu.eudat.models.data.grant.Grant grant = new eu.eudat.models.data.grant.Grant(); GrantImportModels grantImport = dataManagementPlans.get(0).getGrantImport(); grant.setId(grantImport.getId()); grant.setLabel(grantImport.getLabel()); grant.setAbbreviation(grantImport.getAbbreviation()); grant.setDescription(grantImport.getDescription()); GrantDMPEditorModel grantEditor = new GrantDMPEditorModel(); grantEditor.setExistGrant(grant); eu.eudat.models.data.project.Project project = new eu.eudat.models.data.project.Project(); ProjectImportModels projectImport = dataManagementPlans.get(0).getProjectImportModels(); project.setId(projectImport.getId()); project.setLabel(projectImport.getLabel()); ProjectDMPEditorModel projectEditor = new ProjectDMPEditorModel(); projectEditor.setExistProject(project); List associatedProfiles = new LinkedList<>(); for (AssociatedProfileImportModels a : dataManagementPlans.get(0).getProfilesImportModels()) { AssociatedProfile associatedProfile = new AssociatedProfile(); associatedProfile.setId(a.getId()); associatedProfile.setLabel(a.getLabel()); associatedProfiles.add(associatedProfile); } List organisations = new ArrayList<>(); for (OrganisationImportModel org : dataManagementPlans.get(0).getOrganisationImportModels()) { eu.eudat.models.data.dmp.Organisation organisation = new eu.eudat.models.data.dmp.Organisation(); organisation.setLabel(org.getOrganaisationNameImport()); organisation.setId(org.getOrganaisationReferenceImport()); organisations.add(organisation); } List researchers = new LinkedList<>(); for (ResearcherImportModels res : dataManagementPlans.get(0).getResearchersImportModels()) { eu.eudat.models.data.dmp.Researcher researcher = new eu.eudat.models.data.dmp.Researcher(); researcher.setLabel(res.getResearcherImportName()); researcher.setId(res.getResearcherImportReference()); researchers.add(researcher); } List associatedUsers = new LinkedList<>(); List dynamicFields = new LinkedList<>(); // Sets properties. dm.setLabel(files[0].getOriginalFilename()); // Sets label. dm.setGrant(grantEditor); //Sets grant property. dm.setFunder(funderEditor); dm.setProject(projectEditor); dm.setDescription(dataManagementPlans.get(0).getDescriptionImport()); // Sets description property. dm.setProfiles(associatedProfiles); dm.setOrganisations(organisations); // Sets organisations property. dm.setResearchers(researchers); // Sets researchers property. dm.setAssociatedUsers(associatedUsers); // Sets associatedUsers property. dm.setDynamicFields(dynamicFields); // Sets dynamicFields property. dm.setDefinition(dmpProfile); //createOrUpdate(apiContext, dm, principal); DMP dmp = this.createOrUpdate(apiContext, dm, principal); if (dmp.getOrganisations() == null) { dmp.setOrganisations(new HashSet<>()); } if (dmp.getResearchers() == null) { dmp.setResearchers(new HashSet<>()); } if (dmp.getDataset() == null) { dmp.setDataset(new HashSet<>()); } if (dmp.getUsers() == null) { dmp.setUsers(new HashSet<>()); } if (dmp.getAssociatedDmps() == null) { dmp.setAssociatedDmps(new HashSet<>()); } List datasets = new LinkedList<>(); for (DatasetImportModels das: dataManagementPlans.get(0).getDatasetImportModels()) { eu.eudat.data.entities.Dataset dataset = new eu.eudat.data.entities.Dataset(); dataset.setLabel(das.getName()); dataset.setProfile(databaseRepository.getDatasetProfileDao().find(das.getProfile())); dataset.setProperties(new ObjectMapper().writeValueAsString(das.getFieldImportModels())); dataset.setStatus((short) 0); dataset.setRegistries(new HashSet<>()); dataset.setDatasetDataRepositories(new HashSet<>()); dataset.setServices(new HashSet<>()); dataset.setDatasetExternalDatasets(new HashSet<>()); dataset.setDmp(dmp); DatasetWizardModel datasetWizard = new DatasetWizardModel(); datasetWizard.setDatasetProfileDefinition(this.datasetManager.getPagedProfile(datasetWizard, dataset)); datasetWizard.fromDataModel(dataset); this.datasetManager.createOrUpdate(datasetWizard, principal); // datasets.add(new DatasetListingModel().fromDataModel(dataset)); } logger.info(dm.toString()); } return dataManagementPlans; } public DataTableData getDatasetProfilesUsedByDMP(DatasetProfileTableRequestItem datasetProfileTableRequestItem, Principal principal) { datasetProfileTableRequestItem.getCriteria().setFilter(DatasetProfileCriteria.DatasetProfileFilter.DMPs.getValue()); datasetProfileTableRequestItem.getCriteria().setUserId(principal.getId()); QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(datasetProfileTableRequestItem.getCriteria()); List listingModels = items.select(item -> new DatasetProfileListingModel().fromDataModel(item)); DataTableData data = new DataTableData<>(); data.setData(listingModels); data.setTotalCount((long) listingModels.size()); return data; } public void makePublic(UUID id, Principal principal) throws Exception { DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id); // Check if dmp is finalized and if user is owner. if (!isUserOwnerOfDmp(dmp, principal)) throw new Exception("User does not have the privilege to do this action."); if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) throw new Exception("DMP is not finalized"); dmp.setPublic(true); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); sendNotification(dmp, user, NotificationType.DMP_PUBLISH); } public void makeFinalize(UUID id, Principal principal, DatasetsToBeFinalized datasetsToBeFinalized) throws Exception { DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id); if (!isUserOwnerOfDmp(dmp, principal)) throw new Exception("User does not have the privilege to do this action."); if (dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) throw new Exception("DMP is already finalized"); dmp.setStatus(DMP.DMPStatus.FINALISED.getValue()); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); if (datasetsToBeFinalized != null && datasetsToBeFinalized.getUuids() != null && !datasetsToBeFinalized.getUuids().isEmpty()) { apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeFinalized.getUuids())) .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); List datasetsToBeCanceled = new LinkedList<>(); for (Dataset dataset : dmp.getDataset()) { if (!dataset.getStatus().equals(Dataset.Status.FINALISED.getValue()) && !datasetsToBeFinalized.getUuids().contains(dataset.getId())) { datasetsToBeCanceled.add(dataset.getId()); } } if (!datasetsToBeCanceled.isEmpty()) apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); } else { List datasetsToBeCanceled = new LinkedList<>(); for (Dataset dataset : dmp.getDataset()) { if (!dataset.getStatus().equals(Dataset.Status.FINALISED.getValue())) { datasetsToBeCanceled.add(dataset.getId()); } } if (!datasetsToBeCanceled.isEmpty()) apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeCanceled)) .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); sendNotification(dmp, user, NotificationType.DMP_FINALISED); } } private boolean isUserOwnerOfDmp(DMP dmp, Principal principal) { return (dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getId()).equals(principal.getId()); } private String getPreviousDOI(UUID groupId, UUID selfId) { DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); List groupIds = new ArrayList<>(); groupIds.add(groupId); criteria.setGroupIds(groupIds); criteria.setAllVersions(true); List dmps = this.databaseRepository.getDmpDao().getWithCriteria(criteria).toList(); String doi = null; for (DMP dmp: dmps) { if (!dmp.getId().equals(selfId)) { if (dmp.getDoi() != null && !dmp.getDoi().isEmpty()) { doi = dmp.getDoi(); } } } return doi; } public String createZenodoDoi(UUID id, Principal principal, ConfigLoader configLoader) throws Exception { DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(id); if (!isUserOwnerOfDmp(dmp, principal)) throw new Exception("User is not authorized to invoke this action"); if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) throw new Exception("DMP is not finalized"); if (dmp.getDoi() != null) throw new Exception("DMP already has a DOI"); // First step, post call to Zenodo, to create the entry. RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.set("accept", "application/json"); headers.setContentType(MediaType.APPLICATION_JSON); String createData = "{\n" + " \"metadata\": {\n" + " \"title\": \"" + dmp.getLabel() + "\",\n" + " \"upload_type\": \"publication\",\n" + " \"publication_type\": \"datamanagementplan\",\n" + " \"description\": \"" + (dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

") + "\",\n" + " \"version\": \"" + dmp.getVersion() + "\",\n" + " \"creators\": [{\n" + " \t\t\"name\": \"" + dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName() + "\",\n" + " \t\t\"affiliation\": \"OpenDMP\"}]\n" + " }\n" + "}"; HttpEntity request = new HttpEntity<>(createData, headers); Map createResponse = null; LinkedHashMap links = null; if (dmp.getVersion() == 0) { String createUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?access_token=" + this.environment.getProperty("zenodo.access_token"); createResponse = restTemplate.postForObject(createUrl, request, Map.class); links = (LinkedHashMap) createResponse.get("links"); } else { //It requires more than one step to create a new version //First, get the deposit related to the concept DOI String listUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + this.getPreviousDOI(dmp.getGroupId(), dmp.getId()) + "\"&access_token=" + this.environment.getProperty("zenodo.access_token"); ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); createResponse = listResponses.getBody()[0]; links = (LinkedHashMap) createResponse.get("links"); //Second, make the new version (not in the links?) String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + this.environment.getProperty("zenodo.access_token"); createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class); links = (LinkedHashMap) createResponse.get("links"); //Third, get the new deposit String latestDraftUrl = links.get("latest_draft") + "?access_token=" + this.environment.getProperty("zenodo.access_token"); createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); links = (LinkedHashMap) createResponse.get("links"); //At this point it might fail to perform the next requests so enclose them with try catch try { //Forth, update the new deposit's metadata String updateUrl = links.get("self") + "?access_token=" + this.environment.getProperty("zenodo.access_token"); restTemplate.put(updateUrl, request); //And finally remove pre-existing files from it String fileListUrl = links.get("self") + "/files" + "?access_token=" + this.environment.getProperty("zenodo.access_token"); ResponseEntity fileListResponse = restTemplate.getForEntity(fileListUrl, Map[].class); for (Map file : fileListResponse.getBody()) { String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + this.environment.getProperty("zenodo.access_token"); restTemplate.delete(fileDeleteUrl); } }catch (Exception e) { //In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed) restTemplate.delete(latestDraftUrl); throw e; } } // Second step, add the file to the entry. HttpHeaders fileHeaders = new HttpHeaders(); fileHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); LinkedMultiValueMap addFileMap = new LinkedMultiValueMap<>(); File file = getWordDocument(id.toString(), principal, configLoader); addFileMap.add("filename", file.getName()); FileSystemResource fileSystemResource = new FileSystemResource(file); addFileMap.add("file", fileSystemResource); HttpEntity> addFileMapRequest = new HttpEntity<>(addFileMap, fileHeaders); String addFileUrl = links.get("files") + "?access_token=" + this.environment.getProperty("zenodo.access_token"); ResponseEntity addFileResponse = restTemplate.postForEntity(addFileUrl, addFileMapRequest, String.class); Files.deleteIfExists(file.toPath()); // Third post call to Zenodo to publish the entry and return the DOI. String publishUrl = links.get("publish") + "?access_token=" + this.environment.getProperty("zenodo.access_token"); Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); dmp.setDoi((String) publishResponce.get("conceptdoi")); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); return (String) publishResponce.get("conceptdoi"); } }