diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..40de9c9ea --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,66 @@ +def pipelineContext = [:] + +pipeline { + agent any + + options { + skipDefaultCheckout(true) + } + + stages { + stage('Checkout') { + steps { + checkout scm + } + } + stage('Build API') { + steps { + script { + pipelineContext.apiImage = docker.build("open-dmp-api:${env.BUILD_ID}", "-f dmp-backend/Dockerfile.CI dmp-backend/") + } + } + } + stage('Build WebApp') { + steps { + script { + pipelineContext.webappImage = docker.build("open-dmp-webapp:${env.BUILD_ID}", "-f dmp-frontend/Dockerfile.CI dmp-frontend/") + } + } + } + //stage('SonarQube analysis') { + // steps { + // script { + // def scannerHome = tool 'SonarQube Scanner 4.3'; + // withSonarQubeEnv('SonarQube') { // If you have configured more than one global server connection, you can specify its name + // sh "${scannerHome}/bin/sonar-scanner" + // } + // } + // } + //} + //// waiting for sonar results based into the configured web hook in Sonar server which push the status back to jenkins + //stage('SonarQube scan result check') { + // steps { + // timeout(time: 2, unit: 'MINUTES') { + // retry(3) { + // script { + // def qg = waitForQualityGate() + // if (qg.status != 'OK') { + // error "Pipeline aborted due to quality gate failure: ${qg.status}" + // } + // } + // } + // } + // } + //} + stage('Pushing to Docker Registry') { + steps { + script { + docker.withRegistry('http://drepo.local.cite.gr', 'b2c651c1-9a3b-4a98-a6da-e1dd7a20f512') { + pipelineContext.apiImage.push() + pipelineContext.webappImage.push() + } + } + } + } + } +} \ No newline at end of file diff --git a/dmp-backend/Dockerfile.CI b/dmp-backend/Dockerfile.CI new file mode 100644 index 000000000..944713adf --- /dev/null +++ b/dmp-backend/Dockerfile.CI @@ -0,0 +1,15 @@ +FROM maven:3-jdk-8-alpine AS MAVEN_BUILD + +COPY pom.xml /build/ +COPY data /build/data/ +COPY elastic /build/elastic/ +COPY queryable /build/queryable/ +COPY web /build/web/ + +WORKDIR /build/ +RUN mvn package + +FROM openjdk:8-jre-alpine +WORKDIR /app +COPY --from=MAVEN_BUILD /build/web/target/web-1.0-SNAPSHOT.jar /app/app.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom" ,"-Dspring.profiles.active=${PROF}","-jar","/app.jar"] \ No newline at end of file diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java index b6fb3c5d4..0074428eb 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java @@ -52,13 +52,12 @@ public class DMPDaoImpl extends DatabaseAccess implements DMPDao { query.where((builder, root) -> root.get("groupId").in(criteria.getGroupIds())); if (criteria.getStatus() != null) { if (criteria.getStatus() == DMP.DMPStatus.FINALISED.getValue()) { - query.where((builder, root) -> builder.and(builder.equal(root.get("status"), DMP.DMPStatus.FINALISED.getValue()), builder.notEqual(root.get("isPublic"), true))); + query.where((builder, root) -> builder.equal(root.get("status"), DMP.DMPStatus.FINALISED.getValue())); } else if (criteria.getStatus() == DMP.DMPStatus.ACTIVE.getValue()) { query.where((builder, root) -> builder.equal(root.get("status"), DMP.DMPStatus.ACTIVE.getValue())); } } - if (criteria.getIsPublic()) - query.where(((builder, root) -> builder.equal(root.get("isPublic"), true))); + query.where(((builder, root) -> builder.equal(root.get("isPublic"), criteria.getIsPublic()))); /*if (criteria.getRole() != null) { if (criteria.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())) { query.where((builder, root) -> builder.equal(root.join("users", JoinType.LEFT).get("role"), UserDMP.UserDMPRoles.OWNER.getValue())); diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java index 6a44d9339..1a475db17 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java @@ -29,7 +29,21 @@ import java.util.stream.Collectors; @NamedEntityGraph( name = "dmpRecentActivity", attributeNodes = { - @NamedAttributeNode("users"), @NamedAttributeNode("creator")}) + @NamedAttributeNode("users"), @NamedAttributeNode("creator")}), + @NamedEntityGraph( + name = "recentDmpModel", + attributeNodes = {@NamedAttributeNode("organisations"), @NamedAttributeNode("researchers"), @NamedAttributeNode("associatedDmps"), + @NamedAttributeNode("grant"), @NamedAttributeNode(value = "users", subgraph = "users"), @NamedAttributeNode("creator"), @NamedAttributeNode("profile"), @NamedAttributeNode(value = "dataset", subgraph = "dataset")}, + subgraphs = { + @NamedSubgraph(name = "users", attributeNodes = {@NamedAttributeNode("user")}), + @NamedSubgraph(name = "dataset", attributeNodes = {@NamedAttributeNode("id"), @NamedAttributeNode("label")}) + } + ), + @NamedEntityGraph( + name = "versionListingModel", + attributeNodes = {@NamedAttributeNode("id"), @NamedAttributeNode("groupId"), @NamedAttributeNode("version")} + ) + }) public class DMP implements DataEntity { diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java index 521dfb45f..66c917cb0 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Dataset.java @@ -36,7 +36,17 @@ import java.util.stream.Collectors; @NamedEntityGraph( name = "datasetDataRepositories", attributeNodes = {@NamedAttributeNode(value = "dmp", subgraph = "dmp"), @NamedAttributeNode("creator")}, - subgraphs = @NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("creator"), @NamedAttributeNode("users")})) + subgraphs = @NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("creator"), @NamedAttributeNode("users")})), + @NamedEntityGraph( + name = "recentDatasetModel", + attributeNodes = {@NamedAttributeNode("services"), @NamedAttributeNode(value = "datasetDataRepositories", subgraph = "datasetDataRepositories"), + @NamedAttributeNode(value = "datasetExternalDatasets", subgraph = "datasetExternalDatasets"), @NamedAttributeNode("registries"), + @NamedAttributeNode(value = "dmp", subgraph = "dmp"), @NamedAttributeNode("profile"), @NamedAttributeNode("creator")}, + subgraphs = { + @NamedSubgraph(name = "dmp", attributeNodes = {@NamedAttributeNode("creator"), @NamedAttributeNode("users"), @NamedAttributeNode("grant"), @NamedAttributeNode("organisations")}), + @NamedSubgraph(name = "datasetDataRepositories", attributeNodes = {@NamedAttributeNode("dataRepository")}), + @NamedSubgraph(name = "datasetExternalDatasets", attributeNodes = {@NamedAttributeNode("externalDataset")}) + }) }) public class Dataset implements DataEntity { diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/query/PaginationService.java b/dmp-backend/data/src/main/java/eu/eudat/data/query/PaginationService.java index 7ee93cd6f..c21344140 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/query/PaginationService.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/query/PaginationService.java @@ -21,9 +21,12 @@ public class PaginationService { items.withFields(Arrays.asList(tableRequest.getSelection().getFields())); return items; } - public static void applyOrder(QueryableList items, TableQuery tableRequest) { - ColumnOrderings columnOrderings = tableRequest.getOrderings(); + applyOrder(items, tableRequest.getOrderings()); + } + + + public static void applyOrder(QueryableList items, ColumnOrderings columnOrderings) { for (Ordering ordering : columnOrderings.getFieldOrderings()) { if (ordering.getOrderByType() == Ordering.OrderByType.ASC) applyAscOrder(items, ordering); diff --git a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java index eb382a81e..e79e91a34 100644 --- a/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java +++ b/dmp-backend/elastic/src/main/java/eu/eudat/elastic/entities/Tag.java @@ -13,6 +13,14 @@ public class Tag implements ElasticEntity { private String id; private String name; + public Tag() { + } + + public Tag(String id, String name) { + this.id = id; + this.name = name; + } + public String getId() { return id; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java index 371a61386..f8844b7d7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java @@ -28,6 +28,8 @@ import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.listingmodels.DataManagementPlanListingModel; import eu.eudat.models.data.listingmodels.DataManagementPlanOverviewModel; +import eu.eudat.models.data.listingmodels.UserInfoListingModel; +import eu.eudat.models.data.listingmodels.VersionListingModel; import eu.eudat.models.data.security.Principal; import eu.eudat.query.DMPQuery; import eu.eudat.types.ApiMessageCode; @@ -55,8 +57,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import static org.springframework.http.MediaType.APPLICATION_ATOM_XML; -import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.http.MediaType.*; @RestController @@ -158,14 +159,26 @@ public class DMPs extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); } + @RequestMapping(method = RequestMethod.GET, value = {"/versions/{id}"}, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity>> getVersions(@PathVariable(value= "id") String groupId, + @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { + List versions = this.dataManagementPlanManager.getAllVersions(groupId, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(versions)); + } + /* * Data Export * */ @RequestMapping(method = RequestMethod.GET, value = {"rda/{id}"}) public @ResponseBody - ResponseEntity getRDAJsonDocument(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IOException { + ResponseEntity getRDAJsonDocument(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + try { return this.dataManagementPlanManager.getRDAJsonDocument(id, datasetManager, principal); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseItem<>().message(e.getMessage()).status(ApiMessageCode.ERROR_MESSAGE)); + } } @RequestMapping(method = RequestMethod.GET, value = {"/getPDF/{id}"}) @@ -199,27 +212,35 @@ public class DMPs extends BaseController { @Transactional @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> createOrUpdate(@RequestBody eu.eudat.models.data.dmp.DataManagementPlanEditorModel dataManagementPlanEditorModel, Principal principal) throws Exception { - DMP dmp = this.dataManagementPlanManager.createOrUpdate(this.getApiContext(), dataManagementPlanEditorModel, principal); + ResponseEntity> createOrUpdate(@RequestBody eu.eudat.models.data.dmp.DataManagementPlanEditorModel dataManagementPlanEditorModel, Principal principal) throws Exception { + DMP dmp = this.dataManagementPlanManager.createOrUpdate(dataManagementPlanEditorModel, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload(new eu.eudat.models.data.dmp.DataManagementPlan().fromDataModel(dmp))); + } + + @Transactional + @RequestMapping(method = RequestMethod.POST, path = "full", consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity> createOrUpdateWithDatasets(@RequestBody eu.eudat.models.data.dmp.DataManagementPlanEditorModel dataManagementPlanEditorModel, Principal principal) throws Exception { + DMP dmp = this.dataManagementPlanManager.createOrUpdateWithDatasets(dataManagementPlanEditorModel, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload(dmp.getId())); } @RequestMapping(method = RequestMethod.POST, value = {"/new/{id}"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> newVersion(@PathVariable UUID id, @Valid @RequestBody eu.eudat.models.data.dmp.DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { + ResponseEntity> newVersion(@PathVariable UUID id, @Valid @RequestBody eu.eudat.models.data.dmp.DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { try { - this.dataManagementPlanManager.newVersion(id, dataManagementPlan, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE)); + UUID result = this.dataManagementPlanManager.newVersion(id, dataManagementPlan, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(result)); } catch (DMPNewVersionException exception) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(exception.getMessage())); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(exception.getMessage())); } } @RequestMapping(method = RequestMethod.POST, value = {"/clone/{id}"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> clone(@PathVariable UUID id, @RequestBody eu.eudat.models.data.dmp.DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { - this.dataManagementPlanManager.clone(dataManagementPlan, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); + ResponseEntity> clone(@PathVariable UUID id, @RequestBody eu.eudat.models.data.dmp.DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { + UUID cloneId = this.dataManagementPlanManager.clone(dataManagementPlan, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).payload(cloneId)); } @Transactional @@ -238,8 +259,10 @@ public class DMPs extends BaseController { public ResponseEntity dmpUpload(@RequestParam("file") MultipartFile[] files, @RequestParam(name = "profiles", required = false)String[] profiles, Principal principal) throws Exception { if (files[0].getContentType().equals(APPLICATION_JSON.toString())) { this.dataManagementPlanManager.createFromRDA(files, principal, profiles); - } else if (files[0].getContentType().equals(APPLICATION_ATOM_XML.toString())) { + } else if (files[0].getContentType().equals(APPLICATION_ATOM_XML.toString()) || files[0].getContentType().equals(TEXT_XML.toString())) { this.dataManagementPlanManager.createDmpFromXml(this.getApiContext(), files, principal); + } else { + return ResponseEntity.badRequest().body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("File format is not supported")); } return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem() .status(ApiMessageCode.SUCCESS_MESSAGE)); @@ -251,7 +274,8 @@ public class DMPs extends BaseController { this.dataManagementPlanManager.makePublic(UUID.fromString(id), principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully Data Datamanagement Plan made public.")); } catch (Exception e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(e.getMessage())); + logger.error(e.getMessage(), e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to make Data Management Plan public.")); } } @@ -262,7 +286,8 @@ public class DMPs extends BaseController { this.dataManagementPlanManager.makeFinalize(UUID.fromString(id), principal, datasetsToBeFinalized); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully Data Datamanagement Plan made finalized.")); } catch (Exception e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(e.getMessage())); + logger.error(e.getMessage(), e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to finalize Data Management Plan.")); } } @@ -273,7 +298,21 @@ public class DMPs extends BaseController { this.dataManagementPlanManager.undoFinalize(UUID.fromString(id), principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully Data Datamanagement Plan made active.")); } catch (Exception e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(e.getMessage())); + logger.error(e.getMessage(), e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to unfinalize the Data Management Plan.")); + } + } + + + @Transactional + @RequestMapping(method = RequestMethod.POST, value = {"/updateusers/{id}"}) + public ResponseEntity> updateUsers(@PathVariable String id, @RequestBody List users, Principal principal) { + try { + this.dataManagementPlanManager.updateUsers(UUID.fromString(id), users, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully Updated Colaborators for Data Datamanagement Plan.")); + } catch (Exception e) { + logger.error(e.getMessage(), e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to update the users of Data Management Plan.")); } } @@ -289,7 +328,7 @@ public class DMPs extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(zenodoDOI)); } catch (Exception e) { logger.error(e.getMessage(), e); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(e.getMessage())); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan.")); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java index dcb99e942..0e3e7d936 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DashBoardController.java @@ -1,9 +1,12 @@ package eu.eudat.controllers; +import eu.eudat.criteria.RecentActivityCriteria; import eu.eudat.logic.managers.DashBoardManager; import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; import eu.eudat.models.data.dashboard.recent.RecentActivity; +import eu.eudat.models.data.dashboard.recent.model.RecentActivityModel; +import eu.eudat.models.data.dashboard.recent.tablerequest.RecentActivityTableRequest; import eu.eudat.models.data.dashboard.searchbar.SearchBarItem; import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics; import eu.eudat.models.data.helpers.responses.ResponseItem; @@ -15,6 +18,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import javax.transaction.Transactional; import java.io.IOException; import java.util.List; @@ -42,6 +46,14 @@ public class DashBoardController extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(statistics)); } + @RequestMapping(method = RequestMethod.POST, value = {"/dashboard/recentActivity"}, produces = "application/json") + @Transactional + public ResponseEntity>> getNewRecentActivity(@RequestBody RecentActivityTableRequest tableRequest, + @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + List statistics = dashBoardManager.getNewRecentActivity(tableRequest, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(statistics)); + } + @RequestMapping(method = RequestMethod.GET, value = {"/user/recentActivity"}, produces = "application/json") public ResponseEntity> getRecentActivity(@RequestParam(name = "numOfActivities", required = false, defaultValue = "5") Integer numberOfActivities, Principal principal) { RecentActivity statistics = dashBoardManager.getRecentActivity(principal, numberOfActivities); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetWizardController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetWizardController.java deleted file mode 100644 index c2b9abc43..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DatasetWizardController.java +++ /dev/null @@ -1,224 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.data.entities.Dataset; -import eu.eudat.data.query.items.item.dataset.DatasetWizardAutocompleteRequest; -import eu.eudat.data.query.items.item.datasetprofile.DatasetProfileWizardAutocompleteRequest; -import eu.eudat.exceptions.datasetwizard.DatasetWizardCannotUnlockException; -import eu.eudat.exceptions.security.UnauthorisedException; -import eu.eudat.logic.managers.DatasetManager; -import eu.eudat.logic.managers.DatasetWizardManager; -import eu.eudat.logic.managers.UserManager; -import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; -import eu.eudat.logic.security.claims.ClaimedAuthorities; -import eu.eudat.logic.services.ApiContext; -import eu.eudat.logic.services.forms.VisibilityRuleService; -import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; -import eu.eudat.models.data.datasetwizard.DataManagentPlanListingModel; -import eu.eudat.models.data.datasetwizard.DatasetWizardModel; -import eu.eudat.models.data.dmp.AssociatedProfile; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.models.data.listingmodels.DataManagementPlanOverviewModel; -import eu.eudat.models.data.security.Principal; -import eu.eudat.models.data.user.composite.PagedDatasetProfile; -import eu.eudat.types.ApiMessageCode; -import eu.eudat.types.Authorities; -import org.apache.poi.util.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.persistence.NoResultException; -import javax.transaction.Transactional; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.util.List; -import java.util.UUID; - -import static eu.eudat.types.Authorities.ANONYMOUS; - - -@RestController -@CrossOrigin -@RequestMapping(value = {"api/datasetwizard"}) -public class DatasetWizardController extends BaseController { - private static final Logger logger = LoggerFactory.getLogger(DatasetWizardController.class); - - private Environment environment; - private DatasetManager datasetManager; - private UserManager userManager; - private ConfigLoader configLoader; - - @Autowired - public DatasetWizardController(ApiContext apiContext, Environment environment, DatasetManager datasetManager, UserManager userManager, ConfigLoader configLoader) { - super(apiContext); - this.environment = environment; - this.datasetManager = datasetManager; - this.userManager = userManager; - this.configLoader = configLoader; - } - - @RequestMapping(method = RequestMethod.POST, value = {"/userDmps"}, produces = "application/json") - public @ResponseBody - ResponseEntity>> getUserDmps(@RequestBody DatasetWizardAutocompleteRequest datasetWizardAutocompleteRequest, Principal principal) throws IllegalAccessException, InstantiationException { - List dataManagementPlans = DatasetWizardManager.getUserDmps(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), datasetWizardAutocompleteRequest, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlans)); - } - - @RequestMapping(method = RequestMethod.POST, value = {"/getAvailableProfiles"}, produces = "application/json") - public @ResponseBody - ResponseEntity>> getAvailableProfiles(@RequestBody DatasetProfileWizardAutocompleteRequest datasetProfileWizardAutocompleteRequest, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) throws IllegalAccessException, InstantiationException { - List dataManagementPlans = DatasetWizardManager.getAvailableProfiles(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), datasetProfileWizardAutocompleteRequest); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlans)); - } - - @Transactional - @RequestMapping(method = RequestMethod.GET, value = {"{id}"}, produces = "application/json") - public @ResponseBody - ResponseEntity getSingle(@PathVariable String id, @RequestHeader("Content-Type") String contentType, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException { - try { - if (contentType.equals("application/xml")) { - VisibilityRuleService visibilityRuleService = this.getApiContext().getUtilitiesService().getVisibilityRuleService(); - return this.datasetManager.getDocument(id, visibilityRuleService, contentType, principal); - } else if (contentType.equals("application/msword")) { - FileEnvelope file = datasetManager.getWordDocumentFile(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService(), principal); - InputStream resource = new FileInputStream(file.getFile()); - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.setContentLength(file.getFile().length()); - responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); - responseHeaders.set("Content-Disposition", "attachment;filename=" + file.getFilename()); - responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); - responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); - - byte[] content = IOUtils.toByteArray(resource); - resource.close(); - Files.deleteIfExists(file.getFile().toPath()); - return new ResponseEntity<>(content, - responseHeaders, - HttpStatus.OK); - } else { - DatasetWizardModel dataset = this.datasetManager.getSingle(id, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); - } - } catch (Exception e) { - if (e instanceof UnauthorisedException) { - if (e instanceof UnauthorisedException) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); - } else if (e instanceof NoResultException) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); - } else { - throw e; - } - } - } - return null; // ???? - } - - @RequestMapping(method = RequestMethod.GET, value = {"/public/{id}"}, produces = "application/json") - public @ResponseBody - ResponseEntity getSinglePublic(@PathVariable String id) throws Exception { - try { - DatasetWizardModel dataset = this.datasetManager.getSinglePublic(id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); - } - catch (Exception ex) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); - } - } - - @Transactional - @RequestMapping(method = RequestMethod.DELETE, value = {"{id}"}, produces = "application/json") - public @ResponseBody - ResponseEntity> delete(@PathVariable(value = "id") UUID id, Principal principal) throws Exception { - new DatasetWizardManager().delete(this.getApiContext(), id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Deleted")); - } - - @Transactional - @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") - public @ResponseBody - ResponseEntity> createOrUpdate(@RequestBody DatasetWizardModel profile, Principal principal) throws Exception { - this.datasetManager.createOrUpdate(profile, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload(null)); - } - - @RequestMapping(method = RequestMethod.GET, value = {"/getPDF/{id}"}) - public @ResponseBody - ResponseEntity getPDFDocument(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException, InterruptedException { - FileEnvelope file = datasetManager.getWordDocumentFile(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService(), principal); - String fileName = file.getFilename(); - if (fileName.endsWith(".docx")){ - fileName = fileName.substring(0, fileName.length() - 5); - } - File pdffile = datasetManager.convertToPDF(file, environment); - InputStream resource = new FileInputStream(pdffile); - - HttpHeaders responseHeaders = new HttpHeaders(); - responseHeaders.setContentLength(pdffile.length()); - responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); - responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName + ".pdf"); - responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); - responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); - - byte[] content = IOUtils.toByteArray(resource); - resource.close(); - Files.deleteIfExists(file.getFile().toPath()); - Files.deleteIfExists(pdffile.toPath()); - return new ResponseEntity<>(content, - responseHeaders, - HttpStatus.OK); - } - - @RequestMapping(method = RequestMethod.GET, value = {"/get/{id}"}, produces = "application/json") - public ResponseEntity> getSingle(@PathVariable String id) { - eu.eudat.data.entities.DatasetProfile profile = this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(id)); - eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = userManager.generateDatasetProfileModel(profile); - PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); - pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(pagedDatasetProfile)); - } - - @Transactional - @RequestMapping(method = RequestMethod.GET, value = {"/{id}/unlock"}, produces = "application/json") - public @ResponseBody - ResponseEntity> unlock(@PathVariable(value = "id") UUID id, Principal principal) throws Exception { - try { - new DatasetWizardManager().unlock(this.getApiContext(), id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Unlocked")); - } catch (DatasetWizardCannotUnlockException datasetWizardCannotUnlockException) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(datasetWizardCannotUnlockException.getMessage())); - } - } - - @RequestMapping(method = RequestMethod.POST, value = {"/upload"}) - public ResponseEntity datasetXmlImport(@RequestParam("file") MultipartFile file, @RequestParam("dmpId") String dmpId, @RequestParam("datasetProfileId") String datasetProfileId, Principal principal) { - try { - Dataset dataset = this.datasetManager.createDatasetFromXml(file, dmpId, datasetProfileId, principal); - if (dataset != null){ - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); - } - else { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message("Import was unsuccessful.")); - } - } catch (Exception e) { - logger.error(e.getMessage(), e); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message("Import was unsuccessful.")); - } - } - - @RequestMapping(method = RequestMethod.GET, value = {"profile/{id}"}, produces = "application/json") - public @ResponseBody - ResponseEntity getSingleProfileUpdate(@PathVariable String id, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException { - DatasetWizardModel dataset = this.datasetManager.datasetUpdateProfile(id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java index 74edf561e..8d186f0b3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Datasets.java @@ -1,42 +1,84 @@ package eu.eudat.controllers; import eu.eudat.data.entities.Dataset; +import eu.eudat.data.query.items.item.dataset.DatasetWizardAutocompleteRequest; +import eu.eudat.data.query.items.item.datasetprofile.DatasetProfileWizardAutocompleteRequest; import eu.eudat.data.query.items.table.dataset.DatasetPublicTableRequest; import eu.eudat.data.query.items.table.dataset.DatasetTableRequest; import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem; +import eu.eudat.exceptions.datasetwizard.DatasetWizardCannotUnlockException; +import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.managers.DatasetManager; +import eu.eudat.logic.managers.DatasetWizardManager; +import eu.eudat.logic.managers.UserManager; +import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; +import eu.eudat.logic.services.forms.VisibilityRuleService; +import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; +import eu.eudat.models.data.dataset.DatasetOverviewModel; import eu.eudat.models.data.datasetprofile.DatasetProfileListingModel; +import eu.eudat.models.data.datasetwizard.DataManagentPlanListingModel; +import eu.eudat.models.data.datasetwizard.DatasetWizardModel; +import eu.eudat.models.data.dmp.AssociatedProfile; import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.listingmodels.DataManagementPlanOverviewModel; import eu.eudat.models.data.listingmodels.DatasetListingModel; import eu.eudat.models.data.security.Principal; +import eu.eudat.models.data.user.composite.PagedDatasetProfile; import eu.eudat.types.ApiMessageCode; import eu.eudat.types.Authorities; +import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import javax.persistence.NoResultException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.List; import java.util.Locale; import java.util.UUID; +import static eu.eudat.types.Authorities.ANONYMOUS; + @RestController @CrossOrigin @RequestMapping(value = {"/api/datasets/"}) public class Datasets extends BaseController { + private static final Logger logger = LoggerFactory.getLogger(Datasets.class); + private Environment environment; private DatasetManager datasetManager; + private ConfigLoader configLoader; + private UserManager userManager; @Autowired - public Datasets(ApiContext apiContext, DatasetManager datasetManager) { + public Datasets(ApiContext apiContext, Environment environment, DatasetManager datasetManager, ConfigLoader configLoader, UserManager userManager) { super(apiContext); + this.environment = environment; this.datasetManager = datasetManager; + this.configLoader = configLoader; + this.userManager = userManager; } + /* + * Data Retrieval + * */ + @RequestMapping(method = RequestMethod.POST, value = {"paged"}, consumes = "application/json", produces = "application/json") public @ResponseBody ResponseEntity>> getPaged(@RequestBody DatasetTableRequest datasetTableRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { @@ -52,12 +94,70 @@ public class Datasets extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); } - @Transactional - @RequestMapping(method = RequestMethod.GET, value = {"/makepublic/{id}"}, produces = "application/json") + @RequestMapping(method = RequestMethod.GET, value = {"/overview/{id}"}) public @ResponseBody - ResponseEntity> makePublic(@PathVariable UUID id, Principal principal, Locale locale) throws Exception { - this.datasetManager.makePublic(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(), id); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message(this.getApiContext().getHelpersService().getMessageSource().getMessage("dataset.public", new Object[]{}, locale))); + ResponseEntity getOverviewSingle(@PathVariable String id,@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + try { + DatasetOverviewModel dataset = this.datasetManager.getOverviewSingle(id, principal, false); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); + } catch (Exception e) { + if (e instanceof UnauthorisedException) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); + } else { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); + } + } + } + + @RequestMapping(method = RequestMethod.GET, value = {"/publicOverview/{id}"}) + public @ResponseBody + ResponseEntity getOverviewSinglePublic(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { +// try { + DatasetOverviewModel dataset = this.datasetManager.getOverviewSingle(id, principal, true); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); +// } catch (Exception ex) { +// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); +// } + } + + @javax.transaction.Transactional + @RequestMapping(method = RequestMethod.GET, value = {"{id}"}, produces = "application/json") + public @ResponseBody + ResponseEntity getSingle(@PathVariable String id, @RequestHeader("Content-Type") String contentType, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException { + try { + if (contentType.equals("application/xml")) { + VisibilityRuleService visibilityRuleService = this.getApiContext().getUtilitiesService().getVisibilityRuleService(); + return this.datasetManager.getDocument(id, visibilityRuleService, contentType, principal); + } else if (contentType.equals("application/msword")) { + FileEnvelope file = datasetManager.getWordDocumentFile(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService(), principal); + InputStream resource = new FileInputStream(file.getFile()); + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentLength(file.getFile().length()); + responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); + responseHeaders.set("Content-Disposition", "attachment;filename=" + file.getFilename()); + responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); + responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); + + byte[] content = IOUtils.toByteArray(resource); + resource.close(); + Files.deleteIfExists(file.getFile().toPath()); + return new ResponseEntity<>(content, + responseHeaders, + HttpStatus.OK); + } else { + DatasetWizardModel dataset = this.datasetManager.getSingle(id, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + if (e instanceof UnauthorisedException) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); + } else if (e instanceof NoResultException) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE)); + } + } } @RequestMapping(method = RequestMethod.POST, value = {"/datasetProfilesUsedByDatasets/paged"}, produces = "application/json") @@ -67,6 +167,143 @@ public class Datasets extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(datasetProfileTableData)); } + @RequestMapping(method = RequestMethod.POST, value = {"/userDmps"}, produces = "application/json") + public @ResponseBody + ResponseEntity>> getUserDmps(@RequestBody DatasetWizardAutocompleteRequest datasetWizardAutocompleteRequest, Principal principal) throws IllegalAccessException, InstantiationException { + List dataManagementPlans = DatasetWizardManager.getUserDmps(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), datasetWizardAutocompleteRequest, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlans)); + } + + @RequestMapping(method = RequestMethod.POST, value = {"/getAvailableProfiles"}, produces = "application/json") + public @ResponseBody + ResponseEntity>> getAvailableProfiles(@RequestBody DatasetProfileWizardAutocompleteRequest datasetProfileWizardAutocompleteRequest, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) throws IllegalAccessException, InstantiationException { + List dataManagementPlans = DatasetWizardManager.getAvailableProfiles(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), datasetProfileWizardAutocompleteRequest); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlans)); + } + + @RequestMapping(method = RequestMethod.GET, value = {"/public/{id}"}, produces = "application/json") + public @ResponseBody + ResponseEntity getSinglePublic(@PathVariable String id) throws Exception { + try { + DatasetWizardModel dataset = this.datasetManager.getSinglePublic(id); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); + } + catch (Exception ex) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message(ex.getMessage())); + } + } + + @RequestMapping(method = RequestMethod.GET, value = {"/get/{id}"}, produces = "application/json") + public ResponseEntity> getSingle(@PathVariable String id) { + eu.eudat.data.entities.DatasetProfile profile = this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(UUID.fromString(id)); + eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = userManager.generateDatasetProfileModel(profile); + PagedDatasetProfile pagedDatasetProfile = new PagedDatasetProfile(); + pagedDatasetProfile.buildPagedDatasetProfile(datasetprofile); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(pagedDatasetProfile)); + } + + @RequestMapping(method = RequestMethod.GET, value = {"profile/{id}"}, produces = "application/json") + public @ResponseBody + ResponseEntity getSingleProfileUpdate(@PathVariable String id, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException { + DatasetWizardModel dataset = this.datasetManager.datasetUpdateProfile(id); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); + } + + /* + * Data Export + * */ + + @RequestMapping(method = RequestMethod.GET, value = {"/getPDF/{id}"}) + public @ResponseBody + ResponseEntity getPDFDocument(@PathVariable String id, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws IllegalAccessException, IOException, InstantiationException, InterruptedException { + FileEnvelope file = datasetManager.getWordDocumentFile(this.configLoader, id, this.getApiContext().getUtilitiesService().getVisibilityRuleService(), principal); + String fileName = file.getFilename(); + if (fileName.endsWith(".docx")){ + fileName = fileName.substring(0, fileName.length() - 5); + } + File pdffile = datasetManager.convertToPDF(file, environment); + InputStream resource = new FileInputStream(pdffile); + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentLength(pdffile.length()); + responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); + responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName + ".pdf"); + responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); + responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); + + byte[] content = IOUtils.toByteArray(resource); + resource.close(); + Files.deleteIfExists(file.getFile().toPath()); + Files.deleteIfExists(pdffile.toPath()); + return new ResponseEntity<>(content, + responseHeaders, + HttpStatus.OK); + } + + /* + * Data Management + * */ + + @javax.transaction.Transactional + @RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity> createOrUpdate(@RequestBody DatasetWizardModel profile, Principal principal) throws Exception { + Dataset dataset = this.datasetManager.createOrUpdate(profile, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Created").payload(dataset.getId())); + } + + @Transactional + @RequestMapping(method = RequestMethod.GET, value = {"/makepublic/{id}"}, produces = "application/json") + public @ResponseBody + ResponseEntity> makePublic(@PathVariable UUID id, Principal principal, Locale locale) throws Exception { + this.datasetManager.makePublic(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(), id); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message(this.getApiContext().getHelpersService().getMessageSource().getMessage("dataset.public", new Object[]{}, locale))); + } + + @javax.transaction.Transactional + @RequestMapping(method = RequestMethod.DELETE, value = {"/delete/{id}"}, produces = "application/json") + public @ResponseBody + ResponseEntity> delete(@PathVariable(value = "id") UUID id, Principal principal) throws Exception { + new DatasetWizardManager().delete(this.getApiContext(), id); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Deleted")); + } + + @javax.transaction.Transactional + @RequestMapping(method = RequestMethod.GET, value = {"/{id}/unlock"}, produces = "application/json") + public @ResponseBody + ResponseEntity> unlock(@PathVariable(value = "id") UUID id, Principal principal) throws Exception { + try { + new DatasetWizardManager().unlock(this.getApiContext(), id); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Unlocked")); + } catch (DatasetWizardCannotUnlockException datasetWizardCannotUnlockException) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message(datasetWizardCannotUnlockException.getMessage())); + } + } + + /* + * Data Import + * */ + + @RequestMapping(method = RequestMethod.POST, value = {"/upload"}) + public ResponseEntity datasetXmlImport(@RequestParam("file") MultipartFile file, @RequestParam("dmpId") String dmpId, @RequestParam("datasetProfileId") String datasetProfileId, Principal principal) { + try { + Dataset dataset = this.datasetManager.createDatasetFromXml(file, dmpId, datasetProfileId, principal); + if (dataset != null){ + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); + } + else { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message("Import was unsuccessful.")); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).message("Import was unsuccessful.")); + } + } + + /* + * Data Index + * */ + @javax.transaction.Transactional @RequestMapping(method = RequestMethod.POST, value = {"/index"}) public @ResponseBody @@ -82,5 +319,7 @@ public class Datasets extends BaseController { this.datasetManager.clearIndex(principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Cleared").payload(null)); } + + } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java index d0591ded6..ff6ddfe92 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/Login.java @@ -31,6 +31,7 @@ import eu.eudat.logic.services.operations.authentication.AuthenticationService; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.login.Credentials; import eu.eudat.models.data.login.LoginInfo; +import eu.eudat.models.data.principal.PrincipalModel; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; import org.slf4j.Logger; @@ -91,17 +92,17 @@ public class Login { @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/externallogin"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> externallogin(@RequestBody LoginInfo credentials) throws GeneralSecurityException, NullEmailException { + ResponseEntity> externallogin(@RequestBody LoginInfo credentials) throws GeneralSecurityException, NullEmailException { logger.info("Trying To Login With " + credentials.getProvider()); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(customAuthenticationProvider.authenticate(credentials)).status(ApiMessageCode.SUCCESS_MESSAGE)); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(customAuthenticationProvider.authenticate(credentials)).status(ApiMessageCode.SUCCESS_MESSAGE)); } @Transactional @RequestMapping(method = RequestMethod.POST, value = {"/nativelogin"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> nativelogin(@RequestBody Credentials credentials) throws NullEmailException { + ResponseEntity> nativelogin(@RequestBody Credentials credentials) throws NullEmailException { logger.info(credentials.getUsername() + " Trying To Login"); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(userManager.authenticate(this.nonVerifiedUserAuthenticationService, credentials)).status(ApiMessageCode.SUCCESS_MESSAGE)); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(userManager.authenticate(this.nonVerifiedUserAuthenticationService, credentials)).status(ApiMessageCode.SUCCESS_MESSAGE)); } @RequestMapping(method = RequestMethod.GET, value = {"/twitterRequestToken"}, produces = "application/json") @@ -148,9 +149,11 @@ public class Login { @RequestMapping(method = RequestMethod.POST, value = {"/me"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity> authMe(Principal principal) throws NullEmailException { + ResponseEntity> authMe(Principal principal) throws NullEmailException { logger.info(principal + " Getting Me"); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(this.nonVerifiedUserAuthenticationService.Touch(principal.getToken())).status(ApiMessageCode.NO_MESSAGE)); + Principal principal1 = this.nonVerifiedUserAuthenticationService.Touch(principal.getToken()); + PrincipalModel principalModel = PrincipalModel.fromEntity(principal1); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(principalModel).status(ApiMessageCode.NO_MESSAGE)); } @Transactional diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java index 727d4f0bf..e80a2c70d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/QuickWizardController.java @@ -1,6 +1,8 @@ package eu.eudat.controllers; +import eu.eudat.data.entities.Dataset; +import eu.eudat.data.entities.DatasetProfile; import eu.eudat.data.entities.Funder; import eu.eudat.data.entities.Project; import eu.eudat.logic.managers.DatasetManager; @@ -86,8 +88,8 @@ public class QuickWizardController extends BaseController { quickWizard.getDmp().setId(dmpEntity.getId()); for (DatasetDescriptionQuickWizardModel dataset : quickWizard.getDatasets().getDatasetsList()) { DataManagementPlan dmp = quickWizard.getDmp().toDataDmp(grantEntity, projectEntity, principal); - UUID uuid = quickWizard.getDmp().getDatasetProfile().getId(); - DatasetWizardModel datasetWizardModel = dataset.toDataModel(dmp, uuid); + DatasetProfile profile = quickWizard.getDmp().getDatasetProfile(); + DatasetWizardModel datasetWizardModel = dataset.toDataModel(dmp, profile); this.datasetManager.createOrUpdate(datasetWizardModel, principal); } @@ -98,7 +100,10 @@ public class QuickWizardController extends BaseController { public @ResponseBody ResponseEntity> addDatasetWizard(@RequestBody DatasetCreateWizardModel datasetCreateWizardModel, Principal principal) throws Exception{ for(DatasetDescriptionQuickWizardModel dataset : datasetCreateWizardModel.getDatasets().getDatasetsList()){ - this.datasetManager.createOrUpdate(dataset.toDataModel(datasetCreateWizardModel.getDmpMeta().getDmp(), datasetCreateWizardModel.getDmpMeta().getDatasetProfile().getId()), principal); + DatasetProfile profile = new DatasetProfile(); + profile.setId(datasetCreateWizardModel.getDmpMeta().getDatasetProfile().getId()); + profile.setLabel(datasetCreateWizardModel.getDmpMeta().getDatasetProfile().getLabel()); + this.datasetManager.createOrUpdate(dataset.toDataModel(datasetCreateWizardModel.getDmpMeta().getDmp(), profile), principal); } return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Dataset added!")); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/TagController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/TagController.java index 029e1ba08..e7acb4f09 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/TagController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/TagController.java @@ -48,8 +48,12 @@ public class TagController extends BaseController { //ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); /*List> remoteRepos = this.getApiContext().getOperationsContext().getRemoteFetcher().getTags(externalUrlCriteria, type); TagExternalSourcesModel researchersExternalSourcesModel = new TagExternalSourcesModel().fromExternalItem(remoteRepos);*/ - List tags = this.getApiContext().getOperationsContext().getElasticRepository().getDatasetRepository().query(new DatasetCriteria()).stream().map(Dataset::getTags).flatMap(Collection::stream).filter(StreamDistinctBy.distinctByKey(Tag::getId)).collect(Collectors.toList()); + if (this.getApiContext().getOperationsContext().getElasticRepository().getDatasetRepository().exists()) { + List tags = this.getApiContext().getOperationsContext().getElasticRepository().getDatasetRepository().query(new DatasetCriteria()).stream().map(Dataset::getTags).flatMap(Collection::stream).filter(StreamDistinctBy.distinctByKey(Tag::getId)).collect(Collectors.toList()); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().payload(tags).status(ApiMessageCode.NO_MESSAGE)); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().payload(tags).status(ApiMessageCode.NO_MESSAGE)); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ResponseItem>().status(ApiMessageCode.ERROR_MESSAGE).message("Elastic Services are not available")); + } } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java index b6d045a67..ecb46650e 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/UserInvitationController.java @@ -14,6 +14,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; +import javax.xml.bind.JAXBException; import java.util.List; import java.util.UUID; @@ -41,7 +42,7 @@ public class UserInvitationController extends BaseController { @Transactional @RequestMapping(method = RequestMethod.GET, value = {"/exchange/{invitationID}"}, produces = "application/json") public @ResponseBody - ResponseEntity> exchange(@PathVariable UUID invitationID, Principal principal) { + ResponseEntity> exchange(@PathVariable UUID invitationID, Principal principal) throws JAXBException { UUID dmpId = invitationsManager.assignUserAcceptedInvitation(invitationID, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).payload(dmpId)); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/criteria/RecentActivityCriteria.java b/dmp-backend/web/src/main/java/eu/eudat/criteria/RecentActivityCriteria.java new file mode 100644 index 000000000..40cf806c1 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/criteria/RecentActivityCriteria.java @@ -0,0 +1,22 @@ +package eu.eudat.criteria; + +public class RecentActivityCriteria { + private String like; + private String order; + + public String getLike() { + return like; + } + + public void setLike(String like) { + this.like = like; + } + + public String getOrder() { + return order; + } + + public void setOrder(String order) { + this.order = order; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/PrincipalBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/PrincipalBuilder.java index 74ca6607b..bc5cce484 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/PrincipalBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/builders/model/models/PrincipalBuilder.java @@ -17,6 +17,7 @@ public class PrincipalBuilder extends Builder { private UUID id; private UUID token; private String name; + private String email; private Date expiresAt; private String avatarUrl; private Set authorities; @@ -43,6 +44,11 @@ public class PrincipalBuilder extends Builder { return this; } + public PrincipalBuilder email(String email) { + this.email = email; + return this; + } + public PrincipalBuilder expiresAt(Date expiresAt) { this.expiresAt = expiresAt; return this; @@ -98,6 +104,7 @@ public class PrincipalBuilder extends Builder { Principal principal = new Principal(); principal.setAuthorities(authorities); principal.setName(name); + principal.setEmail(email); principal.setExpiresAt(expiresAt); principal.setToken(token); principal.setId(id); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java index 50e45f103..62b5fa194 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DashBoardManager.java @@ -1,38 +1,59 @@ package eu.eudat.logic.managers; -import eu.eudat.data.dao.criteria.*; +import eu.eudat.data.dao.criteria.DataManagementPlanCriteria; +import eu.eudat.data.dao.criteria.DatasetCriteria; +import eu.eudat.data.dao.criteria.GrantCriteria; +import eu.eudat.data.dao.criteria.OrganisationCriteria; import eu.eudat.data.dao.entities.DMPDao; import eu.eudat.data.dao.entities.DatasetDao; -import eu.eudat.data.dao.entities.OrganisationDao; import eu.eudat.data.dao.entities.GrantDao; -import eu.eudat.data.entities.*; -import eu.eudat.data.query.items.table.dmp.DataManagmentPlanPublicTableRequest; +import eu.eudat.data.dao.entities.OrganisationDao; +import eu.eudat.data.entities.DMP; +import eu.eudat.data.entities.Dataset; +import eu.eudat.data.entities.Grant; +import eu.eudat.data.entities.UserInfo; +import eu.eudat.data.query.PaginationService; import eu.eudat.elastic.entities.Dmp; import eu.eudat.logic.builders.model.models.RecentActivityDataBuilder; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.operations.DatabaseRepository; +import eu.eudat.models.HintedModelFactory; import eu.eudat.models.data.dashboard.recent.RecentActivity; import eu.eudat.models.data.dashboard.recent.RecentActivityData; +import eu.eudat.models.data.dashboard.recent.model.RecentActivityModel; +import eu.eudat.models.data.dashboard.recent.model.RecentDatasetModel; +import eu.eudat.models.data.dashboard.recent.model.RecentDmpModel; +import eu.eudat.models.data.dashboard.recent.tablerequest.RecentActivityTableRequest; import eu.eudat.models.data.dashboard.searchbar.SearchBarItem; import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics; import eu.eudat.models.data.security.Principal; +import eu.eudat.queryable.QueryableList; import eu.eudat.types.searchbar.SearchBarItemType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import javax.transaction.Transactional; import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; +import java.util.stream.Stream; @Component public class DashBoardManager { private static final Logger logger = LoggerFactory.getLogger(DashBoardManager.class); + private final Map> comparators = Stream.of(new Object[][] { + { "modified", Comparator.comparing(o -> ((RecentActivityModel)o).getModified()).reversed()}, + { "created", Comparator.comparing(o -> ((RecentActivityModel)o).getCreated()).reversed()}, + { "label", Comparator.comparing(o -> ((RecentActivityModel)o).getTitle())}, + { "status", Comparator.comparing(o -> ((RecentActivityModel)o).getStatus()).reversed()}, + { "finalizedAt", Comparator.comparing(o -> ((RecentActivityModel)o).getFinalizedAt(), Comparator.nullsLast(Comparator.naturalOrder())).reversed()}, + { "publishedAt", Comparator.comparing(o -> ((RecentActivityModel)o).getPublishedAt(), Comparator.nullsLast(Comparator.naturalOrder())).reversed()} + }).collect(Collectors.toMap(data -> (String) data[0], data -> (Comparator)data[1])); + private ApiContext apiContext; private DatabaseRepository databaseRepository; @@ -45,17 +66,12 @@ public class DashBoardManager { public DashBoardStatistics getStatistics() { DashBoardStatistics statistics = new DashBoardStatistics(); - DataManagmentPlanPublicTableRequest publicTableRequest = new DataManagmentPlanPublicTableRequest(); - - DataManagementPlanPublicCriteria publicCriteria = new DataManagementPlanPublicCriteria(); - + DataManagementPlanCriteria publicCriteria = new DataManagementPlanCriteria(); + publicCriteria.setIsPublic(true); + publicCriteria.setOnlyPublic(true); publicCriteria.setAllVersions(false); - publicTableRequest.setCriteria(publicCriteria); - - publicTableRequest.setQuery(databaseRepository.getDmpDao().asQueryable()); - - List dmps = publicTableRequest.applyCriteria().toList(); + List dmps = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(publicCriteria).toList(); // DataManagementPlanCriteria dataManagementPlanCriteria = new DataManagementPlanCriteria(); OrganisationCriteria organisationCriteria = new OrganisationCriteria(); @@ -121,10 +137,10 @@ public class DashBoardManager { List roles = new LinkedList<>(); List finalDmps = dmps; - CompletableFuture dmpFuture = dataManagementPlanRepository.getAuthenticated(dmps != null ? dataManagementPlanRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDmps.stream().map(Dmp::getId).collect(Collectors.toList()))) : dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria), principal.getId(), roles).countAsync() + CompletableFuture dmpFuture = dataManagementPlanRepository.getAuthenticated((dmps != null && !dmps.isEmpty()) ? dataManagementPlanRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDmps.stream().map(Dmp::getId).collect(Collectors.toList()))) : dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria), principal.getId(), roles).distinct().countAsync() .whenComplete((dmpsStats, throwable) -> statistics.setTotalDataManagementPlanCount(dmpsStats)); List finalDatasets = datasets; - CompletableFuture datasetFuture = datasetRepository.getAuthenticated(datasets != null ? datasetRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDatasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList()))) : datasetRepository.getWithCriteria(datasetCriteria), user, roles).countAsync() + CompletableFuture datasetFuture = datasetRepository.getAuthenticated((datasets != null && !datasets.isEmpty()) ? datasetRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDatasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList()))) : datasetRepository.getWithCriteria(datasetCriteria), user, roles).countAsync() .whenComplete((datasetsStats, throwable) -> statistics.setTotalDataSetCount(datasetsStats)); CompletableFuture grantFuture = grantRepository.getAuthenticated(grantRepository.getWithCriteria(grantCriteria), user).countAsync() .whenComplete((grantsStats, throwable) -> statistics.setTotalGrantCount(grantsStats)); @@ -175,6 +191,135 @@ public class DashBoardManager { return activity; } + @Transactional + public List getNewRecentActivity(RecentActivityTableRequest tableRequest, Principal principal) { + boolean isAuthenticated = principal.getId() != null; + List recentActivityModels = new ArrayList<>(); + DMPDao dataManagementPlanRepository = databaseRepository.getDmpDao(); + DatasetDao datasetRepository = databaseRepository.getDatasetDao(); + UserInfo user = new UserInfo(); + if (isAuthenticated) { + user.setId(principal.getId()); + } + DatasetCriteria datasetCriteria = new DatasetCriteria(); + datasetCriteria.setLike(tableRequest.getCriteria().getLike()); + datasetCriteria.setAllVersions(false); + datasetCriteria.setIsPublic(!isAuthenticated); + DataManagementPlanCriteria dataManagementPlanCriteria = new DataManagementPlanCriteria(); + dataManagementPlanCriteria.setAllVersions(false); + dataManagementPlanCriteria.setLike(tableRequest.getCriteria().getLike()); + dataManagementPlanCriteria.setIsPublic(!isAuthenticated); + dataManagementPlanCriteria.setOnlyPublic(!isAuthenticated); + + QueryableList dmpList; + QueryableList datasetList; + + List datasets = null; + List dmps = null; + + if (apiContext.getOperationsContext().getElasticRepository().getDatasetRepository() != null) { + try { + eu.eudat.elastic.criteria.DatasetCriteria datasetElasticCriteria = new eu.eudat.elastic.criteria.DatasetCriteria(); + datasetElasticCriteria.setLike(tableRequest.getCriteria().getLike()); + datasetElasticCriteria.setAllowAllVersions(false); + datasetElasticCriteria.setPublic(!isAuthenticated); + datasets = apiContext.getOperationsContext().getElasticRepository().getDatasetRepository().query(datasetElasticCriteria); + }catch (Exception e) { + logger.warn(e.getMessage(), e); + datasets = null; + } + } + + if (apiContext.getOperationsContext().getElasticRepository().getDmpRepository() != null) { + try { + eu.eudat.elastic.criteria.DmpCriteria dmpElasticCriteria = new eu.eudat.elastic.criteria.DmpCriteria(); + dmpElasticCriteria.setLike(tableRequest.getCriteria().getLike()); + dmpElasticCriteria.setAllowAllVersions(false); + dmpElasticCriteria.setPublic(!isAuthenticated); + dmps = apiContext.getOperationsContext().getElasticRepository().getDmpRepository().query(dmpElasticCriteria); + }catch (Exception e) { + logger.warn(e.getMessage(), e); + datasets = null; + } + } + + if (dmps != null && !dmps.isEmpty()) { + List finalDmps = dmps; + dmpList = dataManagementPlanRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDmps.stream().map(Dmp::getId).collect(Collectors.toList()))).distinct(); + } else { + dmpList = dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria).distinct(); + } + + if (datasets != null && !datasets.isEmpty()) { + List finalDatasets = datasets; + datasetList = datasetRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDatasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList()))); + } else { + datasetList = datasetRepository.getWithCriteria(datasetCriteria); + } + + if (isAuthenticated) { + + List roles = new LinkedList<>(); + dmpList = dataManagementPlanRepository.getAuthenticated(dmpList, principal.getId(), roles); + datasetList = datasetRepository.getAuthenticated(datasetList, user, roles); + + } + + PaginationService.applyOrder(dmpList, tableRequest.getOrderings()); + for (int i = 0; i< tableRequest.getOrderings().getFields().length; i++) { + if (tableRequest.getOrderings().getFields()[i].contains("publishedAt")) { + String newField = tableRequest.getOrderings().getFields()[i].toCharArray()[0] + "dmp:publishedAt|join|"; + tableRequest.getOrderings().getFields()[i] = newField; + } + } + PaginationService.applyOrder(datasetList, tableRequest.getOrderings()); + + /*CompletableFuture future = CompletableFuture.runAsync(() -> */{ + recentActivityModels.addAll(dmpList + .withHint(HintedModelFactory.getHint(RecentDmpModel.class)) + // .orderBy((builder, root) -> builder.desc(root.get(tableRequest.getCriteria().getOrder()))) + .skip(tableRequest.getDmpOffset()) + .take(tableRequest.getLength()) + .select(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(x -> x.getUser().getId().equals(principal.getId())) + .collect(Collectors.toList()).size() > 0) + .collect(Collectors.toSet())); + return new RecentDmpModel().fromEntity(item); + })); + + recentActivityModels.addAll(datasetList + .withHint(HintedModelFactory.getHint(RecentDatasetModel.class)) + // .orderBy((builder, root) -> builder.desc(root.get(tableRequest.getCriteria().getOrder()))) + .skip(tableRequest.getDatasetOffset()) + .take(tableRequest.getLength()) + .select(item -> { + return new RecentDatasetModel().fromEntity(item); + })); + }/*);*/ + + //GK: Shuffle the deck otherwise we will summon the DMPodia when sorting with status + int pos = -1; + for (int i = (recentActivityModels.size() / 2); i < recentActivityModels.size(); i++) { + RecentActivityModel recentActivityModel = recentActivityModels.remove(i); + while (pos < recentActivityModels.size()) { + pos++; + if (pos % 2 != 0) { + break; + } + } + recentActivityModels.add(pos, recentActivityModel); + } + + //CompletableFuture.allOf(future).join(); + // CompletableFuture.allOf(dmps, datasets).join(); + + return recentActivityModels.stream().sorted(this.comparators.get(tableRequest.getCriteria().getOrder())).limit(tableRequest.getLength()).collect(Collectors.toList()); + } + public List searchUserData(String like, Principal principal) { UserInfo user = new UserInfo(); user.setId(principal.getId()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 8d272f67d..ad66be3b5 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -50,10 +50,7 @@ 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.listingmodels.*; import eu.eudat.models.data.project.ProjectDMPEditorModel; import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.user.composite.PagedDatasetProfile; @@ -87,6 +84,7 @@ import java.io.*; import java.math.BigInteger; import java.nio.file.Files; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @@ -158,6 +156,7 @@ public class DataManagementPlanManager { if (fieldsGroup.equals("listing")) { if (!dataManagementPlanTableRequest.getCriteria().isOnlyPublic()) { itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class)) + .distinct() .selectAsync(item -> { item.setDataset( item.getDataset().stream() @@ -171,6 +170,7 @@ public class DataManagementPlanManager { .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } else { itemsFuture = pagedItems.withHint(HintedModelFactory.getHint(DataManagementPlanListingModel.class)) + .distinct() .selectAsync(item -> { item.setDataset( item.getDataset().stream() @@ -181,15 +181,17 @@ public class DataManagementPlanManager { } } else if (fieldsGroup.equals("autocomplete")) { itemsFuture = pagedItems + .distinct() .selectAsync(item -> new DataManagementPlanListingModel().fromDataModelAutoComplete(item)) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } else { itemsFuture = pagedItems + .distinct() .selectAsync(item -> new DataManagementPlanListingModel().fromDataModelAssociatedProfiles(item)) .whenComplete((resultList, throwable) -> dataTable.setData(resultList)); } - CompletableFuture countFuture = authItems.countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count)); + CompletableFuture countFuture = authItems.distinct().countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count)); CompletableFuture.allOf(itemsFuture, countFuture).join(); return dataTable; } @@ -207,6 +209,24 @@ public class DataManagementPlanManager { throw new ForbiddenException("Selected DMP is not public"); } dataManagementPlan.fromDataModel(dataManagementPlanEntity); + List datasetEnities = new ArrayList<>(dataManagementPlanEntity.getDataset()); + /*for (int i = 0; i < datasetEnities.size(); i++) { + for (int j = i; j < dataManagementPlan.getDatasets().size(); j++) { + if (dataManagementPlan.getDatasets().get(j).getId().equals(datasetEnities.get(i).getId())) { + dataManagementPlan.getDatasets().get(j).setDatasetProfileDefinition(datasetManager.getPagedProfile(dataManagementPlan.getDatasets().get(j), datasetEnities.get(i))); + break; + } + } + }*/ + datasetEnities.stream() + .filter(dataset -> !dataset.getStatus().equals(Dataset.Status.DELETED) && !dataset.getStatus().equals(Dataset.Status.CANCELED)) + .forEach(dataset -> { + dataManagementPlan.getDatasets().stream().filter(datasetWizardModel -> datasetWizardModel.getId().equals(dataset.getId())).forEach(datasetWizardModel -> { + DatasetWizardModel wizardModel = datasetManager.getSingle(datasetWizardModel.getId().toString(), principal); + datasetWizardModel.setDatasetProfileDefinition(wizardModel.getDatasetProfileDefinition()); + datasetWizardModel.setTags(wizardModel.getTags()); + }); + }); if (isPublic) { dataManagementPlan.setDatasets(dataManagementPlan.getDatasets().stream().filter(dataset -> dataset.getStatus() == Dataset.Status.FINALISED.getValue()).collect(Collectors.toList())); } @@ -301,19 +321,49 @@ public class DataManagementPlanManager { return data; } + public List getAllVersions(String groupId, Principal principal) { + UUID principalId = principal.getId(); + List versions = new ArrayList<>(); + QueryableList items = null; + QueryableList authItems = null; + List roles = new LinkedList<>(); + DataManagementPlanCriteria criteria = new DataManagementPlanCriteria(); + criteria.setGroupIds(Collections.singletonList(UUID.fromString(groupId))); + criteria.setAllVersions(true); + criteria.setIsPublic(principalId == null); + criteria.setOnlyPublic(principalId == null); + items = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getWithCriteria(criteria); + if (principalId != null) { + authItems = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().getAuthenticated(items, principalId, roles); + } else { + authItems = items; + } + CompletableFuture> versionFuture = authItems.withHint(HintedModelFactory.getHint(VersionListingModel.class)) + .orderBy(((builder, root) -> builder.desc(root.get("version")))) + .selectAsync(item -> new VersionListingModel().fromDataModel(item)) + .whenComplete(((versionListingModels, throwable) -> versions.addAll(versionListingModels))); + + CompletableFuture.allOf(versionFuture).join(); + + return versions; + } + /* * Data Management * */ - public DMP createOrUpdate(ApiContext apiContext, DataManagementPlanEditorModel dataManagementPlan, Principal principal) throws Exception { + public DMP createOrUpdate(DataManagementPlanEditorModel dataManagementPlan, Principal principal) throws Exception { boolean setNotification = false; if (dataManagementPlan.getId() != null) { DMP dmp1 = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(dataManagementPlan.getId()); + + Instant dbTime = Instant.ofEpochMilli(dmp1.getModified().getTime()).truncatedTo(ChronoUnit.SECONDS); + Instant modelTime = Instant.ofEpochMilli(dataManagementPlan.getModified().getTime()).truncatedTo(ChronoUnit.SECONDS); 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()) { + if (dbTime.toEpochMilli() != modelTime.toEpochMilli()) { throw new Exception("Another user have already edit that DMP."); } List datasetList = new ArrayList<>(dmp1.getDataset()); @@ -360,7 +410,9 @@ public class DataManagementPlanManager { } } - checkIfUserCanEditGrant(newDmp, user); + if (newDmp.getGrant().getType().equals(Grant.GrantType.INTERNAL.getValue())) { + checkIfUserCanEditGrant(newDmp, user); + } assignGrandUserIfInternal(newDmp, user); assignFunderUserIfInternal(newDmp, user); assignProjectUserIfInternal(newDmp, user); @@ -382,11 +434,14 @@ public class DataManagementPlanManager { apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(dataManagementPlan.getDatasetsToBeFinalized())) .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); + apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() + .asQueryable().where((builder, root) -> root.get("id").in(dataManagementPlan.getDatasetsToBeFinalized())) + .update(root -> root.get("finalizedat"), new Date()); 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())); + for (DatasetWizardModel dataset : dataManagementPlan.getDatasets()) { + if (!(dataset.getStatus() == (int) Dataset.Status.FINALISED.getValue()) && !dataManagementPlan.getDatasetsToBeFinalized().contains(dataset.getId())) { + datasetsToBeCanceled.add(UUID.fromString(dataset.getId().toString())); } } if (!datasetsToBeCanceled.isEmpty()) @@ -395,9 +450,9 @@ public class DataManagementPlanManager { .update(root -> root.get("status"), Dataset.Status.CANCELED.getValue()); } else { List datasetsToBeCanceled = new LinkedList<>(); - for (DatasetListingModel dataset : dataManagementPlan.getDatasets()) { + for (DatasetWizardModel dataset : dataManagementPlan.getDatasets()) { if (!(dataset.getStatus() == (int) Dataset.Status.FINALISED.getValue())) { - datasetsToBeCanceled.add(UUID.fromString(dataset.getId())); + datasetsToBeCanceled.add(dataset.getId()); } } if (!datasetsToBeCanceled.isEmpty()) @@ -423,7 +478,49 @@ public class DataManagementPlanManager { return newDmp; } - public void newVersion(UUID uuid, DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { + public DMP createOrUpdateWithDatasets(DataManagementPlanEditorModel dataManagementPlan, Principal principal) throws Exception { + if (dataManagementPlan.getId() != null) { + DMP dmp1 = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(dataManagementPlan.getId()); + + Instant dbTime = Instant.ofEpochMilli(dmp1.getModified().getTime()).truncatedTo(ChronoUnit.SECONDS); + Instant modelTime = Instant.ofEpochMilli(dataManagementPlan.getModified().getTime()).truncatedTo(ChronoUnit.SECONDS); + + if (!isUserOwnerOfDmp(dmp1, principal)) { + throw new Exception("User not being the creator is not authorized to edit this DMP."); + } + if (dbTime.toEpochMilli() != modelTime.toEpochMilli()) { + throw new Exception("Another user have already edit that DMP."); + } + for (DatasetWizardModel dataset : dataManagementPlan.getDatasets()) { + 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."); + } + List datasets = new ArrayList<>(); + DMP tempDMP = dataManagementPlan.toDataModel(); + if (tempDMP.getStatus() == (int) DMP.DMPStatus.FINALISED.getValue()) { + checkDmpValidationRules(tempDMP); + } + UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); + createOrganisationsIfTheyDontExist(tempDMP, apiContext.getOperationsContext().getDatabaseRepository().getOrganisationDao()); + createResearchersIfTheyDontExist(tempDMP, apiContext.getOperationsContext().getDatabaseRepository().getResearcherDao(), user); + createFunderIfItDoesntExist(tempDMP, apiContext.getOperationsContext().getDatabaseRepository().getFunderDao()); + createGrantIfItDoesntExist(tempDMP, apiContext.getOperationsContext().getDatabaseRepository().getGrantDao()); + + DMP result = createOrUpdate(dataManagementPlan, principal); + + for (DatasetWizardModel datasetWizardModel: dataManagementPlan.getDatasets()) { + datasetWizardModel.setDmp(new DataManagementPlan().fromDataModel(result)); + Dataset dataset = datasetManager.createOrUpdate(datasetWizardModel, principal); + datasets.add(dataset); + } + + return result; + } + + public UUID 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."); @@ -473,13 +570,13 @@ public class DataManagementPlanManager { newDmp.setDataset(new HashSet<>(databaseRepository.getDatasetDao().getWithCriteria(criteria1).toList())); this.updateGroupIndex(newDmp.getGroupId()); - + return newDmp.getId(); } else { throw new DMPNewVersionException("Version to update not the latest."); } } - public void clone(DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { + public UUID clone(DataManagementPlanNewVersionModel dataManagementPlan, Principal principal) throws Exception { DMP newDmp = dataManagementPlan.toDataModel(); UserInfo user = apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class).id(principal.getId()).build(); @@ -515,6 +612,8 @@ public class DataManagementPlanManager { newDmp.setDataset(new HashSet<>(databaseRepository.getDatasetDao().getWithCriteria(criteria1).toList())); this.updateIndex(newDmp); + + return newDmp.getId(); } public void delete(UUID uuid) throws DMPWithDatasetsDeleteException, IOException { @@ -817,8 +916,15 @@ public class DataManagementPlanManager { apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeFinalized.getUuids())) .update(root -> root.get("status"), Dataset.Status.FINALISED.getValue()); + apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao() + .asQueryable().where((builder, root) -> root.get("id").in(datasetsToBeFinalized.getUuids())) + .update(root -> root.get("finalizedAt"), new Date()); List finalizedDatasets = dmp.getDataset().stream().filter(dataset -> datasetsToBeFinalized.getUuids().contains(dataset.getId())).collect(Collectors.toList()); - finalizedDatasets.forEach(dataset -> dataset.setStatus(Dataset.Status.FINALISED.getValue())); + finalizedDatasets.forEach(dataset ->{ + dataset.setStatus(Dataset.Status.FINALISED.getValue()); + dataset.setFinalizedAt(new Date()); + dataset.setModified(new Date()); + } ); indexDatasets.addAll(finalizedDatasets); List datasetsToBeCanceled = new LinkedList<>(); for (Dataset dataset : dmp.getDataset()) { @@ -867,12 +973,24 @@ public class DataManagementPlanManager { this.updateIndex(dmp); } + public void updateUsers(UUID id, List users, Principal principal) 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."); + clearUsers(dmp); + for (UserInfoListingModel userListing : users) { + UserInfo tempUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userListing.getId()); + assignUser(dmp, tempUser, UserDMP.UserDMPRoles.fromInteger(userListing.getRole())); + } + + } + /* * Export Data * */ public FileEnvelope getWordDocument(String id, Principal principal, ConfigLoader configLoader) throws IOException { - return this.getWordDocument(id, principal, configLoader, false); + return this.getWordDocument(id, principal, configLoader, true); } public FileEnvelope getWordDocument(String id, Principal principal, ConfigLoader configLoader, Boolean versioned) throws IOException { @@ -1021,11 +1139,9 @@ public class DataManagementPlanManager { document.removeBodyElement(0); } - String fileName = ""; + String fileName = "DMP_" + dmpEntity.getGrant().getLabel(); if (versioned) { - fileName = dmpEntity.getLabel() + " v" + dmpEntity.getVersion(); - } else { - fileName = dmpEntity.getLabel(); + fileName += "_" + dmpEntity.getVersion(); } fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); FileEnvelope exportEnvelope = new FileEnvelope(); @@ -1171,7 +1287,7 @@ public class DataManagementPlanManager { writer.close(); FileEnvelope fileEnvelope = new FileEnvelope(); fileEnvelope.setFile(xmlFile); - fileEnvelope.setFilename(dmp.getLabel() + ".xml"); + fileEnvelope.setFilename("DMP_" + dmp.getGrant().getLabel() + "_" + dmp.getVersion() + ".xml"); return fileEnvelope; } @@ -1185,7 +1301,7 @@ public class DataManagementPlanManager { /*ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);*/ - String fileName = dmp.getLabel(); + String fileName = "DMP_" + dmp.getGrant().getLabel() + "_" + dmp.getVersion();//dmp.getLabel(); fileName = fileName.replaceAll("[^a-zA-Z0-9+ ]", ""); String uuid = UUID.randomUUID().toString(); File file = new File(this.environment.getProperty("temp.temp") + uuid + ".json"); @@ -1341,7 +1457,7 @@ public class DataManagementPlanManager { dm.setDefinition(dmpProfile); //createOrUpdate(apiContext, dm, principal); - DMP dmp = this.createOrUpdate(apiContext, dm, principal); + DMP dmp = this.createOrUpdate(dm, principal); if (dmp.getOrganisations() == null) { dmp.setOrganisations(new HashSet<>()); } @@ -1672,21 +1788,26 @@ public class DataManagementPlanManager { dataBuilder.append(" \"description\": \"").append((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

")).append("\",\n"); dataBuilder.append(" \"version\": \"").append(dmp.getVersion()).append("\",\n"); dataBuilder.append(" \"access_right\": \""); - if (((Boolean)extraProperties.get("visible"))) { - Instant publicationDate = Instant.parse(extraProperties.get("publicDate").toString()); - if (publicationDate.isBefore(Instant.now())) { - dataBuilder.append("open\",\n"); - } else { - dataBuilder.append("embargoed\",\n"); - dataBuilder.append(" \"embargo_date\": \"" + publicationDate + "\",\n"); - } - - if (extraProperties.get("license") != null) { - dataBuilder.append(" \"license\": \"").append(((Map)extraProperties.get("license")).get("pid")).append("\",\n"); - } - } else { + if (extraProperties.get("visible") == null) { dataBuilder.append("restricted\",\n"); dataBuilder.append(" \"access_conditions\": \"\",\n"); + } else { + if (((Boolean) extraProperties.get("visible"))) { + Instant publicationDate = Instant.parse(extraProperties.get("publicDate").toString()); + if (publicationDate.isBefore(Instant.now())) { + dataBuilder.append("open\",\n"); + } else { + dataBuilder.append("embargoed\",\n"); + dataBuilder.append(" \"embargo_date\": \"" + publicationDate + "\",\n"); + } + + if (extraProperties.get("license") != null) { + dataBuilder.append(" \"license\": \"").append(((Map) extraProperties.get("license")).get("pid")).append("\",\n"); + } + } else { + dataBuilder.append("restricted\",\n"); + dataBuilder.append(" \"access_conditions\": \"\",\n"); + } } if (dmp.isPublic()) { dataBuilder.append(" \"related_identifiers\": [{\n"); @@ -1797,21 +1918,17 @@ public class DataManagementPlanManager { if (!update) { if (unpublishedUrl == null) { // Second step, add the file to the entry. - HttpHeaders fileHeaders = new HttpHeaders(); - fileHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); - LinkedMultiValueMap addFileMap = new LinkedMultiValueMap<>(); - FileEnvelope file = getWordDocument(id.toString(), principal, configLoader); - addFileMap.add("filename", file.getFilename()); - FileSystemResource fileSystemResource = new FileSystemResource(file.getFile()); - addFileMap.add("file", fileSystemResource); - HttpEntity> addFileMapRequest = new HttpEntity<>(addFileMap, fileHeaders); + String name = file.getFilename().substring(0, file.getFilename().length() - 5); + File pdfFile = datasetManager.convertToPDF(file, environment); + String fileName = name + ".pdf"; + FileSystemResource fileSystemResource = new FileSystemResource(pdfFile); + HttpEntity addFileMapRequest = new HttpEntity<>(fileSystemResource, null); - String addFileUrl = links.get("files") + "?access_token=" + zenodoToken; - ResponseEntity addFileResponse = restTemplate.postForEntity(addFileUrl, addFileMapRequest, String.class); + String addFileUrl = links.get("bucket") + "/" + fileName + "?access_token=" + zenodoToken; + restTemplate.put(addFileUrl, addFileMapRequest); Files.deleteIfExists(file.getFile().toPath()); - // Third post call to Zenodo to publish the entry and return the DOI. publishUrl = links.get("publish") + "?access_token=" + zenodoToken; } else { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataRepositoryManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataRepositoryManager.java index 31634fe0c..fc6cb8f9d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataRepositoryManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataRepositoryManager.java @@ -38,7 +38,7 @@ public class DataRepositoryManager { public List getDataRepositories(String query, String type, Principal principal) throws HugeResultSet, NoURLFound { ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); - List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getRepositories(externalUrlCriteria, type); + List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getRepositories(externalUrlCriteria, type); DataRepositoryCriteria criteria = new DataRepositoryCriteria(); if (!query.isEmpty()) criteria.setLike(query); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java index feff5dda3..c3f137c9f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetManager.java @@ -17,6 +17,7 @@ import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequest import eu.eudat.elastic.criteria.DatasetCriteria; import eu.eudat.elastic.entities.Tag; import eu.eudat.elastic.repository.DatasetRepository; +import eu.eudat.exceptions.security.ForbiddenException; import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.builders.BuilderFactory; import eu.eudat.logic.builders.entity.UserInfoBuilder; @@ -32,9 +33,11 @@ import eu.eudat.logic.utilities.documents.xml.ExportXmlBuilder; import eu.eudat.logic.utilities.helpers.StreamDistinctBy; import eu.eudat.logic.utilities.json.JsonSearcher; import eu.eudat.models.HintedModelFactory; +import eu.eudat.models.data.dataset.DatasetOverviewModel; import eu.eudat.models.data.datasetImport.DatasetImportField; import eu.eudat.models.data.datasetImport.DatasetImportPagedDatasetProfile; import eu.eudat.models.data.datasetprofile.DatasetProfileListingModel; +import eu.eudat.models.data.datasetprofile.DatasetProfileOverviewModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.dmp.AssociatedProfile; import eu.eudat.models.data.dmp.DataManagementPlan; @@ -49,6 +52,7 @@ import org.apache.poi.xwpf.extractor.XWPFWordExtractor; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; +import org.json.JSONArray; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,6 +71,7 @@ import org.w3c.dom.NodeList; import javax.activation.MimetypesFileTypeMap; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; +import javax.transaction.Transactional; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; @@ -163,7 +168,7 @@ public class DatasetManager { QueryableList authItems; if (!datasetTableRequest.getCriteria().getIsPublic()) { if (principal.getId() == null) { - throw new UnauthorisedException(); + throw new UnauthorisedException("You are not allowed to access those datasets"); } if (datasetTableRequest.getCriteria().getRole() != null) roles.add(datasetTableRequest.getCriteria().getRole()); @@ -177,24 +182,19 @@ public class DatasetManager { }); } String[] strings = new String[1]; - strings[0] = "-dmp:publishedAt|join|"; - datasetTableRequest.getOrderings().setFields(strings); + //strings[0] = "-dmp:publishedAt|join|"; + //datasetTableRequest.getOrderings().setFields(strings); authItems = items; pagedItems = PaginationManager.applyPaging(items, datasetTableRequest); } DataTableData dataTable = new DataTableData<>(); - CompletableFuture> itemsFuture = pagedItems. - selectAsync(item -> new DatasetListingModel().fromDataModel(item)).whenComplete((resultList, throwable) -> { - dataTable.setData(resultList); - }); + dataTable.setData(pagedItems.select(this::mapModel).stream().filter(Objects::nonNull).collect(Collectors.toList())); - CompletableFuture countFuture = authItems.countAsync().whenComplete((count, throwable) -> { - dataTable.setTotalCount(count); - }); + dataTable.setTotalCount(authItems.count()); - CompletableFuture.allOf(itemsFuture, countFuture).join(); + //CompletableFuture.allOf(itemsFuture, countFuture).join(); return dataTable; } @@ -240,8 +240,8 @@ public class DatasetManager { DataTableData dataTable = new DataTableData<>(); CompletableFuture> itemsFuture = pagedItems. - selectAsync(item -> new DatasetListingModel().fromDataModel(item)).whenComplete((resultList, throwable) -> { - dataTable.setData(resultList); + selectAsync(this::mapModel).whenComplete((resultList, throwable) -> { + dataTable.setData(resultList.stream().filter(Objects::nonNull).collect(Collectors.toList())); }); CompletableFuture countFuture = pagedItems.countAsync().whenComplete((count, throwable) -> { @@ -257,7 +257,7 @@ public class DatasetManager { eu.eudat.data.entities.Dataset datasetEntity = databaseRepository.getDatasetDao().find(UUID.fromString(id), HintedModelFactory.getHint(DatasetWizardModel.class)); if (datasetEntity.getDmp().getUsers() .stream().filter(userInfo -> userInfo.getUser().getId() == principal.getId()) - .collect(Collectors.toList()).size() == 0) + .collect(Collectors.toList()).size() == 0 && !datasetEntity.getDmp().isPublic()) throw new UnauthorisedException(); eu.eudat.elastic.entities.Dataset datasetElastic; try { @@ -296,7 +296,11 @@ public class DatasetManager { Stream sorted = profileVersionsIncluded.stream().sorted(Comparator.comparing(DatasetProfile::getVersion).reversed()); // Make the Stream into List and get the first item. - DatasetProfile profile = sorted.collect(Collectors.toList()).iterator().next(); + List profiles = sorted.collect(Collectors.toList()); + if (profiles.isEmpty()) + throw new NoSuchElementException("No profiles found for the specific Dataset"); + + DatasetProfile profile = profiles.get(0); // Check if the dataset is on the latest Version. boolean latestVersion = profile.getVersion().toString().equals(datasetEntity.getProfile().getVersion().toString()); @@ -325,6 +329,26 @@ public class DatasetManager { } } + public DatasetOverviewModel getOverviewSingle(String id, Principal principal, boolean isPublic) throws Exception { + Dataset datasetEntity = databaseRepository.getDatasetDao().find(UUID.fromString(id)); + if (datasetEntity.getStatus() == Dataset.Status.DELETED.getValue()) { + throw new Exception("Dataset is deleted."); + } + if (!isPublic && principal == null) { + throw new UnauthorisedException(); + } else + if (!isPublic && datasetEntity.getDmp().getUsers() + .stream().noneMatch(userInfo -> userInfo.getUser().getId() == principal.getId())) { + throw new UnauthorisedException(); + } else if (isPublic && !datasetEntity.getDmp().isPublic()) { + throw new ForbiddenException("Selected Dataset is not public"); + } + DatasetOverviewModel dataset = new DatasetOverviewModel(); + dataset.fromDataModel(datasetEntity); + + return dataset; + } + public PagedDatasetProfile getPagedProfile(DatasetWizardModel dataset, eu.eudat.data.entities.Dataset datasetEntity) { eu.eudat.models.data.user.composite.DatasetProfile datasetprofile = userManager.generateDatasetProfileModel(datasetEntity.getProfile()); datasetprofile.setStatus(dataset.getStatus()); @@ -584,7 +608,7 @@ public class DatasetManager { if (datasetWizardModel.getDmp().getGrant() == null) { datasetWizardModel.setDmp(new DataManagementPlan().fromDataModelNoDatasets(dataset1.getDmp())); } - dataset1.setProfile(this.apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(datasetWizardModel.getProfile())); + dataset1.setProfile(this.apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().find(datasetWizardModel.getProfile().getId())); // datasetWizardModel.setDatasetProfileDefinition(getPagedProfile(datasetWizardModel, dataset1)); updateTags(dataset1, datasetWizardModel.getTags()); if (sendNotification) { @@ -916,7 +940,7 @@ public class DatasetManager { // Sets the latest version of dataet Profile to the Dataset in question. dataset.setDatasetProfileDefinition(getLatestDatasetProfile(datasetEntity, item)); - dataset.setProfile(item.getId()); + dataset.setProfile(new DatasetProfileOverviewModel().fromDataModel(item)); // Now at latest version. dataset.setIsProfileLatestVersion(true); @@ -995,15 +1019,12 @@ public class DatasetManager { if (!tagNodes.isEmpty()) { tagNodes.forEach(node -> { JsonNode value = node.get("value"); - if (value.isArray()) { - value.elements().forEachRemaining(element -> { - try { - Map data = mapper.readValue(element.asText(), HashMap.class); - this.addTag(tags, wizardModel.getTags(), data.get("id"), data.get("name")); - } catch (IOException e) { - logger.error(e.getMessage(), e); - } - + String stringValue = value.asText().replaceAll("=", ":"); + JSONArray values = new JSONArray(stringValue); + if (values != null) { + values.iterator().forEachRemaining(element -> { + Map data = ((JSONObject) element).toMap(); + this.addTag(tags, wizardModel.getTags(), data.get("id").toString(), data.get("name").toString()); }); } else { this.addTag(tags, wizardModel.getTags(), "", value.asText()); @@ -1024,4 +1045,21 @@ public class DatasetManager { dstTags.add(tag); } } + + @Transactional + private DatasetListingModel mapModel(Dataset item) { + if (item.getProfile() == null) + return null; + DatasetListingModel listingModel = new DatasetListingModel().fromDataModel(item); + DatasetProfileCriteria criteria = new DatasetProfileCriteria(); + criteria.setGroupIds(Collections.singletonList(item.getProfile().getGroupId())); + List profiles = apiContext.getOperationsContext().getDatabaseRepository().getDatasetProfileDao().getWithCriteria(criteria).toList(); + boolean islast = false; + if (!profiles.isEmpty()) { + profiles = profiles.stream().sorted(Comparator.comparing(DatasetProfile::getVersion)).collect(Collectors.toList()); + islast = profiles.get(0).getId().equals(item.getProfile().getId()); + } + listingModel.setProfileLatestVersion(islast); + return listingModel; + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java index c22bbd666..362acb233 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DatasetProfileManager.java @@ -26,6 +26,10 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.http.*; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; @@ -109,7 +113,9 @@ public class DatasetProfileManager { public List getAutocomplete(AutoCompleteData data, String like) { List result = new LinkedList<>(); - RestTemplate restTemplate = new RestTemplate(); + SimpleClientHttpRequestFactory simpleFactory = new SimpleClientHttpRequestFactory(); + + RestTemplate restTemplate = new RestTemplate(simpleFactory); HttpHeaders headers = new HttpHeaders(); DocumentContext jsonContext = null; HttpEntity entity; @@ -122,8 +128,12 @@ public class DatasetProfileManager { String url = singleData.getUrl(); String mediaType = ""; - if (url.contains("openaire")) { - mediaType = "application/json; charset=utf-8"; + if (url.contains("openaire") || url.contains("zenodo")) { + mediaType = "application/json; charset=utf-8"; + if (url.contains("zenodo")) { + url = url.replace("?", "/?"); + } + url = url.replace("{like}", like.equals("") ? "*" : like); url = url.replace("%20", " "); url = url.replace("%22", "\""); @@ -133,14 +143,17 @@ public class DatasetProfileManager { url += "?search=" + like; } - headers.setAccept(Collections.singletonList(MediaType.valueOf(mediaType))); + if (!url.contains("zenodo")) { + headers.setAccept(Collections.singletonList(MediaType.valueOf(mediaType))); + } headers.setContentType(MediaType.APPLICATION_JSON); entity = new HttpEntity<>("parameters", headers); + response = restTemplate.exchange(url, HttpMethod.GET, entity, Object.class); jsonContext = JsonPath.parse(response.getBody()); jsonItems = jsonContext.read(singleData.getOptionsRoot() + "['" + singleData.getAutoCompleteOptions().getLabel() + "','" + singleData.getAutoCompleteOptions().getValue() + "','" + singleData.getAutoCompleteOptions().getSource() + "','" + "uri" + "']"); - jsonItems.forEach(item -> result.add(new ExternalAutocompleteFieldModel(item.get(singleData.getAutoCompleteOptions().getValue()), item.get(singleData.getAutoCompleteOptions().getLabel()), item.get(singleData.getAutoCompleteOptions().getSource()), item.get("uri")))); + jsonItems.forEach(item -> result.add(new ExternalAutocompleteFieldModel(item.get(singleData.getAutoCompleteOptions().getValue()), item.get(singleData.getAutoCompleteOptions().getLabel()), item.get(singleData.getAutoCompleteOptions().getSource()) != null ? item.get(singleData.getAutoCompleteOptions().getSource()) : singleData.getAutoCompleteOptions().getSource(), item.get("uri")))); break; case CACHED: headers.setAccept(Collections.singletonList(MediaType.valueOf("text/plain; charset=utf-8"))); @@ -199,7 +212,10 @@ public class DatasetProfileManager { public eu.eudat.logic.utilities.documents.xml.datasetProfileXml.datasetProfileModel.DatasetProfile createDatasetProfileFromXml(MultipartFile multiPartFile) { ImportXmlBuilderDatasetProfile xmlBuilder = new ImportXmlBuilderDatasetProfile(); try { - return xmlBuilder.build(convert(multiPartFile)); + File localFile = convert(multiPartFile); + eu.eudat.logic.utilities.documents.xml.datasetProfileXml.datasetProfileModel.DatasetProfile profile = xmlBuilder.build(localFile); + Files.deleteIfExists(localFile.toPath()); + return profile; } catch (IOException e) { logger.error(e.getMessage(), e); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ExternalDatasetManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ExternalDatasetManager.java index f8f72ce31..2d8f12fa7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ExternalDatasetManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ExternalDatasetManager.java @@ -57,7 +57,7 @@ public class ExternalDatasetManager { // Fetch external Datasets from external sources. ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); - List> remoteRepos = remoteFetcher.getDatasets(externalUrlCriteria, type); + List> remoteRepos = remoteFetcher.getDatasets(externalUrlCriteria, type); // Parse items from external sources to listing models. ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java index a14a1e8df..fd4567e03 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/FunderManager.java @@ -42,7 +42,7 @@ public class FunderManager { QueryableList authItems = apiContext.getOperationsContext().getDatabaseRepository().getFunderDao().getAuthenticated(items, userInfo); List funders = authItems.select(item -> new eu.eudat.models.data.funder.Funder().fromDataModel(item)); ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(funderCriteria.getCriteria().getLike()); - List> remoteRepos = remoteFetcher.getFunders(externalUrlCriteria); + List> remoteRepos = remoteFetcher.getFunders(externalUrlCriteria); FundersExternalSourcesModel fundersExternalSourcesModel = new FundersExternalSourcesModel().fromExternalItem(remoteRepos); for (ExternalSourcesItemModel externalListingItem : fundersExternalSourcesModel) { eu.eudat.models.data.funder.Funder funder = apiContext.getOperationsContext().getBuilderFactory().getBuilder(FunderBuilder.class) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java index e020593ed..885940a36 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/GrantManager.java @@ -126,7 +126,7 @@ public class GrantManager { QueryableList authItems = apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().getAuthenticated(items, userInfo); List grants = authItems.select(item -> new Grant().fromDataModel(item)); - List> remoteRepos = remoteFetcher.getGrants(externalUrlCriteria); + List> remoteRepos = remoteFetcher.getGrants(externalUrlCriteria); GrantsExternalSourcesModel grantsExternalSourcesModel = new GrantsExternalSourcesModel().fromExternalItem(remoteRepos); for (ExternalSourcesItemModel externalListingItem : grantsExternalSourcesModel) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java index b01ca6c94..21d131df3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/InvitationsManager.java @@ -7,15 +7,18 @@ import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.utilities.helpers.StreamDistinctBy; import eu.eudat.models.data.invitation.Invitation; +import eu.eudat.models.data.invitation.Properties; import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.userinfo.UserInfoInvitationModel; +import eu.eudat.queryable.QueryableList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import java.io.StringReader; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,12 +35,19 @@ public class InvitationsManager { public void inviteUsers(Invitation invitation, Principal principal) throws Exception { UserInfo principalUser = new UserInfo(); principalUser.setId(principal.getId()); + invitation.getUsers().stream().filter(item -> item.getId() == null).forEach(item -> { + UserInfo existingUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().asQueryable().where((builder, root) -> builder.equal(root.get("email"), item.getEmail())).getSingleOrDefault(); + if (existingUser != null) { + item.setId(existingUser.getId()); + } + }); List alreadySignedInUsers = invitation.getUsers().stream().filter(item -> item.getId() != null).collect(Collectors.toList()); List alreadySignedInUsersEntities = alreadySignedInUsers.stream().map(UserInfoInvitationModel::toDataModel).collect(Collectors.toList()); List userInfoToUserDmp = new LinkedList<>(); for (UserInfo userInfo : alreadySignedInUsersEntities) { UserDMP userDMP = new UserDMP(); userDMP.setUser(userInfo); + userDMP.setRole(invitation.getRole()); userInfoToUserDmp.add(userDMP); /*if (!apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().areAssociated(principalUser, userInfo)) { UserAssociation userAssociation = new UserAssociation(); @@ -47,7 +57,7 @@ public class InvitationsManager { }*/ } DMP dataManagementPlan = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(invitation.getDataManagementPlan()); - apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), apiContext.getUtilitiesService().getMailService(), invitation.getUsers().stream().map(UserInfoInvitationModel::toDataModel).collect(Collectors.toList()), dataManagementPlan, principalUser); + apiContext.getUtilitiesService().getInvitationService().createInvitations(apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao(), apiContext.getUtilitiesService().getMailService(), invitation.getUsers().stream().map(UserInfoInvitationModel::toDataModel).collect(Collectors.toList()), dataManagementPlan, invitation.getRole(), principalUser); apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userInfoToUserDmp, dataManagementPlan); } @@ -69,27 +79,50 @@ public class InvitationsManager { return userModels; } - public UUID assignUserAcceptedInvitation(UUID invitationID, Principal principal) throws UnauthorisedException { + public UUID assignUserAcceptedInvitation(UUID invitationID, Principal principal) throws UnauthorisedException, JAXBException { eu.eudat.data.entities.Invitation invitation = apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().find(invitationID); if (invitation == null) throw new UnauthorisedException("There is no Data Management Plan assigned to this Link"); if (invitation.getAcceptedInvitation()) throw new UnauthorisedException("This Url Has Expired"); + JAXBContext context = JAXBContext.newInstance(Properties.class); + Unmarshaller unmarshaller = context.createUnmarshaller(); + Properties properties = (Properties) unmarshaller.unmarshal(new StringReader(invitation.getProperties())); UserInfo invitedUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId()); - UserDMP userDMP = new UserDMP(); - userDMP.setUser(invitedUser); - userDMP.setDmp(invitation.getDmp()); - userDMP.setRole(UserDMP.UserDMPRoles.USER.getValue()); + QueryableList userDMPQueryableList = apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().asQueryable().where(((builder, root) -> builder.and(builder.equal(root.get("dmp").get("id"), invitation.getDmp().getId()), builder.equal(root.get("user").get("id"), invitedUser.getId())))); + UserDMP existingUserDMP = userDMPQueryableList.getSingleOrDefault(); + if (existingUserDMP != null) { + if (properties.getRole() != null && existingUserDMP.getRole() > properties.getRole()) { + existingUserDMP.setRole(properties.getRole()); + DMP datamanagementPlan = invitation.getDmp(); + apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().createOrUpdate(existingUserDMP); + apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), existingUserDMP, datamanagementPlan); + invitation.setAcceptedInvitation(true); + apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().createOrUpdate(invitation); + return datamanagementPlan.getId(); + } + } else { + UserDMP userDMP = new UserDMP(); + userDMP.setUser(invitedUser); + userDMP.setDmp(invitation.getDmp()); + + if (properties.getRole() != null) { + userDMP.setRole(properties.getRole()); + } else { + userDMP.setRole(UserDMP.UserDMPRoles.USER.getValue()); + } /*if (!apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().areAssociated(invitedUser, invitation.getUser())) { UserAssociation userAssociation = new UserAssociation(); userAssociation.setFirstUser(invitedUser); userAssociation.setSecondUser(invitation.getUser()); apiContext.getOperationsContext().getDatabaseRepository().getUserAssociationDao().createOrUpdate(userAssociation); }*/ - DMP datamanagementPlan = invitation.getDmp(); - apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().createOrUpdate(userDMP); - apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userDMP, datamanagementPlan); - invitation.setAcceptedInvitation(true); - apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().createOrUpdate(invitation); - return datamanagementPlan.getId(); + DMP datamanagementPlan = invitation.getDmp(); + apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().createOrUpdate(userDMP); + apiContext.getUtilitiesService().getInvitationService().assignToDmp(apiContext.getOperationsContext().getDatabaseRepository().getDmpDao(), userDMP, datamanagementPlan); + invitation.setAcceptedInvitation(true); + apiContext.getOperationsContext().getDatabaseRepository().getInvitationDao().createOrUpdate(invitation); + return datamanagementPlan.getId(); + } + return invitation.getDmp().getId(); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/LicenseManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/LicenseManager.java index da06aedd3..fe174fe29 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/LicenseManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/LicenseManager.java @@ -33,7 +33,7 @@ public class LicenseManager { public List getLicenses(String query, String type) throws HugeResultSet, NoURLFound { ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); - List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getlicenses(externalUrlCriteria, type); + List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getlicenses(externalUrlCriteria, type); DataRepositoryCriteria criteria = new DataRepositoryCriteria(); if (!query.isEmpty()) criteria.setLike(query); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java index 5e67be552..0860c3391 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/OrganisationsManager.java @@ -68,7 +68,7 @@ public class OrganisationsManager { public List getCriteriaWithExternal(String query, String type) throws HugeResultSet, NoURLFound { ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); - List> remoteRepos = apiContext.getOperationsContext().getRemoteFetcher().getOrganisations(externalUrlCriteria, type); + List> remoteRepos = apiContext.getOperationsContext().getRemoteFetcher().getOrganisations(externalUrlCriteria, type); OrganisationsExternalSourcesModel organisationsExternalSourcesModel = new OrganisationsExternalSourcesModel().fromExternalItem(remoteRepos); List organisations = new LinkedList<>(); for (ExternalSourcesItemModel externalListingItem : organisationsExternalSourcesModel) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java index 6919a5de5..f02242826 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ProjectManager.java @@ -41,7 +41,7 @@ public class ProjectManager { QueryableList authItems = apiContext.getOperationsContext().getDatabaseRepository().getProjectDao().getAuthenticated(items, userInfo); List projects = authItems.select(item -> new Project().fromDataModel(item)); ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(projectCriteria.getCriteria().getLike()); - List> remoteRepos = remoteFetcher.getProjects(externalUrlCriteria); + List> remoteRepos = remoteFetcher.getProjects(externalUrlCriteria); ProjectsExternalSourcesModel projectsExternalSourcesModel = new ProjectsExternalSourcesModel().fromExternalItem(remoteRepos); for (ExternalSourcesItemModel externalListingItem : projectsExternalSourcesModel) { eu.eudat.models.data.project.Project project = apiContext.getOperationsContext().getBuilderFactory().getBuilder(ProjectBuilder.class) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RegistryManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RegistryManager.java index 9220d6221..c9444e002 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RegistryManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/RegistryManager.java @@ -39,7 +39,7 @@ public class RegistryManager { public List getRegistries(String query, String type, Principal principal) throws HugeResultSet, NoURLFound { ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); - List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getRegistries(externalUrlCriteria, type); + List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getRegistries(externalUrlCriteria, type); RegistryCriteria criteria = new RegistryCriteria(); if (!query.isEmpty()) criteria.setLike(query); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java index 0d9104056..e7c54eecc 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ResearcherManager.java @@ -57,7 +57,7 @@ public class ResearcherManager { item.setTag(keyToSourceMap.get(item.getKey())); } ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(researcherCriteriaRequest.getCriteria().getName()); - List> remoteRepos = remoteFetcher.getResearchers(externalUrlCriteria,null); + List> remoteRepos = remoteFetcher.getResearchers(externalUrlCriteria,null); ResearchersExternalSourcesModel researchersExternalSourcesModel = new ResearchersExternalSourcesModel().fromExternalItem(remoteRepos); for (ExternalSourcesItemModel externalListingItem : researchersExternalSourcesModel) { eu.eudat.models.data.dmp.Researcher researcher = apiContext.getOperationsContext().getBuilderFactory().getBuilder(ResearcherBuilder.class) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ServiceManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ServiceManager.java index 222aa3675..2b724ca27 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ServiceManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/ServiceManager.java @@ -36,7 +36,7 @@ public class ServiceManager { public List getServices(String query, String type, Principal principal) throws HugeResultSet, NoURLFound { ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); - List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getServices(externalUrlCriteria, type); + List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().getServices(externalUrlCriteria, type); ServiceCriteria criteria = new ServiceCriteria(); if (!query.isEmpty()) criteria.setLike(query); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java index dd47937b0..572f8e64b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/UserManager.java @@ -24,6 +24,7 @@ import eu.eudat.models.data.dmp.DataManagementPlan; import eu.eudat.models.data.doi.DOIRequest; import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.login.Credentials; +import eu.eudat.models.data.principal.PrincipalModel; import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.models.data.userinfo.UserProfile; @@ -105,10 +106,11 @@ public class UserManager { .createOrUpdate(userInfo); } - public Principal authenticate(AuthenticationService authenticationServiceImpl, Credentials credentials) throws NullEmailException { + public PrincipalModel authenticate(AuthenticationService authenticationServiceImpl, Credentials credentials) throws NullEmailException { Principal principal = authenticationServiceImpl.Touch(credentials); if (principal == null) throw new UnauthorisedException("Could not Sign In User"); - return principal; + PrincipalModel principalModel = PrincipalModel.fromEntity(principal); + return principalModel; } public DataTableData getCollaboratorsPaged(UserInfoTableRequestItem userInfoTableRequestItem, Principal principal) throws Exception { diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java index c9a3723f0..46d4f632b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DatasetMapper.java @@ -3,9 +3,7 @@ package eu.eudat.logic.mapper.elastic; import eu.eudat.data.dao.criteria.DataManagementPlanCriteria; import eu.eudat.data.entities.DMP; import eu.eudat.elastic.criteria.DatasetCriteria; -import eu.eudat.elastic.entities.Collaborator; import eu.eudat.elastic.entities.Dataset; -import eu.eudat.elastic.entities.Organization; import eu.eudat.elastic.entities.Tag; import eu.eudat.logic.managers.DatasetManager; import eu.eudat.logic.services.ApiContext; @@ -25,6 +23,9 @@ public class DatasetMapper { } public Dataset toElastic(eu.eudat.data.entities.Dataset dataset, List tags) throws Exception { + if (dataset.getProfile() == null) { + return null; + } Dataset elastic = new Dataset(); elastic.setId(dataset.getId().toString()); if (tags != null && !tags.isEmpty()) { @@ -36,6 +37,9 @@ public class DatasetMapper { tags.forEach(tag -> tag.setId(UUID.randomUUID().toString())); elastic.setTags(tags); } else { + if (tags1.size() < tags.size()) { + tags.stream().filter(tag -> tag.getId() == null || tag.getId().equals("")).forEach(tag -> tags1.add(new Tag(UUID.randomUUID().toString(), tag.getName()))); + } elastic.setTags(tags1); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DmpMapper.java b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DmpMapper.java index 956af3b5b..608da5fca 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DmpMapper.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/mapper/elastic/DmpMapper.java @@ -1,9 +1,7 @@ package eu.eudat.logic.mapper.elastic; import eu.eudat.data.dao.criteria.DataManagementPlanCriteria; -import eu.eudat.data.dao.entities.DMPDao; import eu.eudat.data.entities.DMP; -import eu.eudat.elastic.entities.Collaborator; import eu.eudat.elastic.entities.Dataset; import eu.eudat.elastic.entities.Dmp; import eu.eudat.elastic.entities.Tag; @@ -12,10 +10,10 @@ import eu.eudat.logic.services.ApiContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; public class DmpMapper { @@ -70,7 +68,7 @@ public class DmpMapper { logger.error(e.getMessage(), e); } return null; - }).collect(Collectors.toList())); + }).filter(Objects::nonNull).collect(Collectors.toList())); } if (dmp.getAssociatedDmps() != null) { elastic.setTemplates(dmp.getAssociatedDmps().stream().map(DatasetTemplateMapper::toElastic).collect(Collectors.toList())); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DataFieldsUrlConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DataFieldsUrlConfiguration.java index 7c746fb85..e027714ed 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DataFieldsUrlConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DataFieldsUrlConfiguration.java @@ -15,6 +15,8 @@ public class DataFieldsUrlConfiguration { private String path; private String host; private String types; + private String firstName; + private String lastName; public String getId() { return id; @@ -94,4 +96,20 @@ public class DataFieldsUrlConfiguration { public void setTypes(String types) { this.types = types; } + + @XmlElement(name = "firstName") + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + @XmlElement(name = "lastName") + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java index 41f42281c..2b0b6c2c1 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java @@ -16,7 +16,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; @@ -183,11 +190,10 @@ public class RemoteFetcher { if (funderId.toCharArray()[0] == ':') { funderId = externalUrlCriteria.getFunderId(); } - try { - funderId = URLEncoder.encode(funderId, "UTF-8"); - } catch (UnsupportedEncodingException e) { - logger.error(e.getMessage(), e); - } + /* + try { funderId = URLEncoder.encode(funderId, "UTF-8"); } catch + (UnsupportedEncodingException e) { logger.error(e.getMessage(), e); } + */ completedPath = completedPath.replace("{funderId}", funderId); } if (externalUrlCriteria.getPage() != null) { @@ -250,21 +256,28 @@ public class RemoteFetcher { private Results getResultsFromUrl(String urlString, DataUrlConfiguration jsonDataPath, String jsonPaginationPath, String contentType) { try { - - URL url = new URL(urlString.replace(" ", "%20")); - - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + HttpEntity entity; + ResponseEntity response; + /* + * URL url = new URL(urlString.replaceAll(" ", "%20")); + * + * HttpURLConnection con = (HttpURLConnection) url.openConnection(); + * con.setRequestMethod("GET"); + */ if (contentType != null && !contentType.isEmpty()) { - con.setRequestProperty("Accept", contentType); + headers.setAccept(Collections.singletonList(MediaType.valueOf(contentType))); } + + entity = new HttpEntity<>("parameters", headers); - int responseCode = con.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_OK) { // success + response = restTemplate.exchange(urlString, HttpMethod.GET, entity, String.class); + if (response.getStatusCode() == HttpStatus.OK) { // success //do here all the parsing Results results = new Results(); - if (con.getHeaderField("Content-Type").contains("json")) { - DocumentContext jsonContext = JsonPath.parse(con.getInputStream()); + if (response.getHeaders().get("Content-Type").get(0).contains("json")) { + DocumentContext jsonContext = JsonPath.parse(response.getBody()); if (jsonDataPath.getFieldsUrlConfiguration().getSource() != null) { results = new Results(jsonContext.read(jsonDataPath.getPath() @@ -278,11 +291,32 @@ public class RemoteFetcher { + "," + jsonDataPath.getFieldsUrlConfiguration().getId() + "]"), new HashMap<>(1, 1)); List> fixedResults = results.getResults().stream().map(item -> { - String id = jsonDataPath.getFieldsUrlConfiguration().getId().replace("'", ""); - if (! (item.get(id) instanceof String)) { - Object obj = item.get(id); - JSONArray jarr = (JSONArray) obj; - item.put(id, jarr.get(0).toString()); + for (int i = 0; i < 2; i++) { + String id; + if (i == 0) { + id = jsonDataPath.getFieldsUrlConfiguration().getId().replace("'", ""); + } else { + id = jsonDataPath.getFieldsUrlConfiguration().getName().replace("'", ""); + } + if (!(item.get(id) instanceof String)) { + Object obj = item.get(id); + if (obj instanceof JSONArray) { + JSONArray jarr = (JSONArray) obj; + if (jarr.get(0) instanceof String) { + item.put(id, jarr.get(0).toString()); + } else { + for (int j = 0; j < jarr.size(); j++) { + mapToMap(id, (Map)jarr.get(j), item, i == 1); + } + } + } else { + if (obj instanceof Map) { + mapToMap(id, (Map) obj, item, i == 1); + } else if (obj != null){ + item.put(id, obj.toString()); + } + } + } } return item; }).collect(Collectors.toList()); @@ -324,6 +358,17 @@ public class RemoteFetcher { results = new Results(finalRes, new HashMap<>(1, 1)); + } else if (jsonDataPath.getFieldsUrlConfiguration().getFirstName() != null) { + results = new Results(jsonContext.read(jsonDataPath.getPath() + + "[" + jsonDataPath.getFieldsUrlConfiguration().getId() + "," + jsonDataPath.getFieldsUrlConfiguration().getFirstName() + + "," + jsonDataPath.getFieldsUrlConfiguration().getLastName() + "]"), + new HashMap<>(1, 1)); + results.getResults().stream().forEach(entry -> { + String name = entry.get(jsonDataPath.getFieldsUrlConfiguration().getFirstName().replace("'", "")) + " " + entry.get(jsonDataPath.getFieldsUrlConfiguration().getLastName().replace("'", "")); + entry.put("name", name); + entry.remove(jsonDataPath.getFieldsUrlConfiguration().getFirstName().replace("'", "")); + entry.remove(jsonDataPath.getFieldsUrlConfiguration().getLastName().replace("'", "")); + }); } else { results = new Results(jsonContext.read(jsonDataPath.getPath() + "[" + jsonDataPath.getFieldsUrlConfiguration().getName() + "," + jsonDataPath.getFieldsUrlConfiguration().getDescription() @@ -333,11 +378,12 @@ public class RemoteFetcher { results.results = results.results.stream().map(e -> e.entrySet().stream().collect(Collectors.toMap(x -> this.transformKey(jsonDataPath,x.getKey()), Map.Entry::getValue))) .collect(Collectors.toList()); } - else if (con.getHeaderField("Content-Type").contains("xml")) { + else if (response.getHeaders().get("Content-Type").get(0).contains("xml")) { Class aClass = Class.forName(jsonDataPath.getParseClass()); JAXBContext jaxbContext = JAXBContext.newInstance(aClass); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - Object data = unmarshaller.unmarshal(con.getInputStream()); + StringReader stringReader = new StringReader(response.getBody()); + Object data = unmarshaller.unmarshal(stringReader); Method reader = null; if (jsonDataPath.getParseField() != null && !jsonDataPath.getParseField().isEmpty()) { reader = new PropertyDescriptor(jsonDataPath.getParseField(), aClass).getReadMethod(); @@ -387,13 +433,7 @@ public class RemoteFetcher { return results; } - } catch (MalformedURLException e1) { - logger.error(e1.getMessage(), e1); - } //maybe print smth... - catch (IOException e2) { - logger.error(e2.getMessage(), e2); - } //maybe print smth... - catch (Exception exception) { + } catch (Exception exception) { logger.error(exception.getMessage(), exception); } //maybe print smth... finally { @@ -472,4 +512,18 @@ public class RemoteFetcher { this.pagination = pagination; } } + + private void mapToMap(String key, Map source, Map destination, boolean isTitle) { + if (source != null) { + String content = source.get("content"); + if (isTitle) { + String classId = source.get("classid"); + if (classId.equals("main title")) { + destination.put(key, content); + } + } else { + destination.put(key, content); + } + } + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java index f002d93d7..a068a5dcb 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/CustomAuthenticationProvider.java @@ -4,6 +4,7 @@ import eu.eudat.exceptions.security.NonValidTokenException; import eu.eudat.exceptions.security.NullEmailException; import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.models.data.login.LoginInfo; +import eu.eudat.models.data.principal.PrincipalModel; import eu.eudat.models.data.security.Principal; import eu.eudat.logic.security.validators.TokenValidatorFactory; import org.slf4j.Logger; @@ -22,11 +23,11 @@ public class CustomAuthenticationProvider { @Autowired private TokenValidatorFactory tokenValidatorFactory; - public Principal authenticate(LoginInfo credentials) throws GeneralSecurityException, NullEmailException { + public PrincipalModel authenticate(LoginInfo credentials) throws GeneralSecurityException, NullEmailException { String token = credentials.getTicket(); try { Principal principal = this.tokenValidatorFactory.getProvider(credentials.getProvider()).validateToken(credentials); - return principal; + return PrincipalModel.fromEntity(principal); } catch (NonValidTokenException e) { logger.error("Could not validate a user by his token! Reason: " + e.getMessage(), e); throw new UnauthorisedException("Token validation failed - Not a valid token"); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java index 6d08acb0c..50d5e12dd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/AbstractAuthenticationService.java @@ -20,7 +20,9 @@ import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import org.springframework.transaction.annotation.Transactional; +import java.sql.Timestamp; import java.time.Instant; +import java.time.LocalDateTime; import java.util.*; public abstract class AbstractAuthenticationService implements AuthenticationService { @@ -98,7 +100,7 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer UserToken userToken = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserTokenBuilder.class) .issuedAt(new Date()).user(credential.getUserInfo()) - .token(UUID.randomUUID()).expiresAt(addADay(new Date())) + .token(UUID.randomUUID()).expiresAt(Timestamp.valueOf(LocalDateTime.now().plusDays(1))) .build(); userToken = apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().createOrUpdate(userToken); @@ -187,7 +189,7 @@ public abstract class AbstractAuthenticationService implements AuthenticationSer UserToken userToken = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserTokenBuilder.class) .token(UUID.randomUUID()).user(userInfo) - .expiresAt(addADay(new Date())).issuedAt(new Date()) + .expiresAt(Timestamp.valueOf(LocalDateTime.now().plusDays(1))).issuedAt(new Date()) .build(); apiContext.getOperationsContext().getDatabaseRepository().getUserTokenDao().createOrUpdate(userToken); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/NonVerifiedUserEmailAuthenticationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/NonVerifiedUserEmailAuthenticationService.java index 4d849a51c..34fa80dc9 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/NonVerifiedUserEmailAuthenticationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/NonVerifiedUserEmailAuthenticationService.java @@ -78,7 +78,9 @@ public class NonVerifiedUserEmailAuthenticationService extends AbstractAuthentic } Principal principal = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(PrincipalBuilder.class) .id(user.getId()).token(token.getToken()) - .expiresAt(token.getExpiresAt()).name(user.getName()) + .expiresAt(token.getExpiresAt()) + .name(user.getName()) + .email(user.getEmail()) .avatarUrl(avatarUrl) .culture(culture) .language(language) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/VerifiedUserAuthenticationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/VerifiedUserAuthenticationService.java index d613b2b47..dfaca0d7a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/VerifiedUserAuthenticationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/authentication/VerifiedUserAuthenticationService.java @@ -87,7 +87,9 @@ public class VerifiedUserAuthenticationService extends AbstractAuthenticationSer } Principal principal = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(PrincipalBuilder.class) .id(user.getId()).token(token.getToken()) - .expiresAt(token.getExpiresAt()).name(user.getName()) + .expiresAt(token.getExpiresAt()) + .name(user.getName()) + .email(user.getEmail()) .avatarUrl(avatarUrl) .culture(culture) .language(language) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationService.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationService.java index a580afc0f..ee4ac3137 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationService.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationService.java @@ -16,7 +16,7 @@ public interface InvitationService { void assignToDmp(DMPDao dmpDao, eu.eudat.data.entities.UserDMP user, DMP dmp); - void createInvitations(InvitationDao invitationDao, MailService mailService, List users, DMP dmp, eu.eudat.data.entities.UserInfo creator) throws MessagingException; + void createInvitations(InvitationDao invitationDao, MailService mailService, List users, DMP dmp, Integer role, eu.eudat.data.entities.UserInfo creator) throws MessagingException; - CompletableFuture sendInvitationAsync(DMP dmp, Invitation invitation, String recipient, MailService mailService) throws MessagingException; + CompletableFuture sendInvitationAsync(DMP dmp, Invitation invitation, String recipient, MailService mailService, Integer role) throws MessagingException; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java index 49027b588..d2d893470 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/utilities/InvitationServiceImpl.java @@ -5,6 +5,8 @@ import eu.eudat.data.dao.entities.DMPDao; import eu.eudat.data.dao.entities.InvitationDao; import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.Invitation; +import eu.eudat.data.entities.UserDMP; +import eu.eudat.models.data.invitation.Properties; import eu.eudat.models.data.mail.SimpleMail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,6 +15,9 @@ import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import javax.mail.MessagingException; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import java.io.StringWriter; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -46,7 +51,7 @@ public class InvitationServiceImpl implements InvitationService { } @Override - public void createInvitations(InvitationDao invitationDao, MailService mailService, List users, DMP dmp, eu.eudat.data.entities.UserInfo creator) throws MessagingException { + public void createInvitations(InvitationDao invitationDao, MailService mailService, List users, DMP dmp, Integer role, eu.eudat.data.entities.UserInfo creator) throws MessagingException { for (eu.eudat.data.entities.UserInfo userInfo : users) { Invitation invitation = new Invitation(); invitation.setDmp(dmp); @@ -54,17 +59,28 @@ public class InvitationServiceImpl implements InvitationService { invitation.setUser(creator); invitation.setToken(UUID.randomUUID()); invitation.setAcceptedInvitation(false); + Properties properties = new Properties(); + properties.setRole(role); + try { + JAXBContext context = JAXBContext.newInstance(Properties.class); + Marshaller marshaller = context.createMarshaller(); + StringWriter propertyWriter = new StringWriter(); + marshaller.marshal(properties, propertyWriter); + invitation.setProperties(propertyWriter.toString()); + }catch (Exception e) { + logger.error(e.getMessage(), e); + } invitationDao.createOrUpdate(invitation); - sendInvitationAsync(dmp, invitation, userInfo.getName(), mailService); + sendInvitationAsync(dmp, invitation, userInfo.getName(), mailService, role); } } @Override - public CompletableFuture sendInvitationAsync(DMP dmp, Invitation invitation, String recipient, MailService mailService) { + public CompletableFuture sendInvitationAsync(DMP dmp, Invitation invitation, String recipient, MailService mailService, Integer role) { return CompletableFuture.runAsync(() -> { SimpleMail mail = new SimpleMail(); mail.setSubject(createSubject(dmp, mailService.getMailTemplateSubject())); - mail.setContent(createContent(invitation.getId(), dmp, recipient, mailService.getMailTemplateContent("classpath:templates/email/email.html"))); + mail.setContent(createContent(invitation.getId(), dmp, recipient, mailService.getMailTemplateContent("classpath:templates/email/email.html"), role)); mail.setTo(invitation.getInvitationEmail()); try { mailService.sendSimpleMail(mail); @@ -79,11 +95,12 @@ public class InvitationServiceImpl implements InvitationService { return subject; } - private String createContent(UUID invitationID, DMP dmp, String recipient, String templateContent) { + private String createContent(UUID invitationID, DMP dmp, String recipient, String templateContent, Integer role) { String content = templateContent.replace("{dmpname}", dmp.getLabel()); content = content.replace("{invitationID}", invitationID.toString()); content = content.replace("{recipient}", recipient); content = content.replace("{host}", this.environment.getProperty("dmp.domain")); + content = content.replace("{dmprole}", UserDMP.UserDMPRoles.fromInteger(role).name()); return content; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java index 9c58e4742..fcad5a7e4 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java @@ -1,20 +1,19 @@ package eu.eudat.logic.utilities.documents.word; -import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.logic.services.forms.VisibilityRuleService; import eu.eudat.logic.utilities.documents.types.ParagraphStyle; import eu.eudat.logic.utilities.interfaces.ApplierWithValue; import eu.eudat.models.data.components.commons.datafield.CheckBoxData; import eu.eudat.models.data.components.commons.datafield.ComboBoxData; +import eu.eudat.models.data.components.commons.datafield.WordListData; import eu.eudat.models.data.user.components.datasetprofile.Field; import eu.eudat.models.data.user.components.datasetprofile.FieldSet; import eu.eudat.models.data.user.components.datasetprofile.Section; import eu.eudat.models.data.user.composite.DatasetProfilePage; import eu.eudat.models.data.user.composite.PagedDatasetProfile; import org.apache.poi.xwpf.usermodel.*; -import org.json.JSONArray; -import org.json.JSONObject; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl; @@ -24,9 +23,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.math.BigInteger; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class WordBuilder { private static final Logger logger = LoggerFactory.getLogger(WordBuilder.class); @@ -234,15 +231,33 @@ public class WordBuilder { String comboboxType = ((ComboBoxData) field.getData()).getType(); if (comboboxType.equals("autocomplete")) { ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); if (field.getValue() == null) return null; - Map map = new HashMap<>(); - if (!field.getValue().equals("")) { + List> mapList = new ArrayList<>(); + if (!field.getValue().equals("") && field.getValue().toString() != null) { try { - JSONArray jsonarray = new JSONArray(field.getValue().toString()); - for (int i = 0; i < jsonarray.length(); i++) { - JSONObject jsonobject = jsonarray.getJSONObject(i); - String id = jsonobject.getString("id"); - String label = jsonobject.getString("label"); + mapList = Arrays.asList(mapper.readValue(field.getValue().toString(), HashMap[].class)); + }catch (Exception e) { + logger.warn(e.getMessage(), e); + Map map = new HashMap<>(); + map.put("label", field.getValue().toString()); + mapList.add(map); + } + /*try { + if (field.getValue().toString().startsWith("[")) { + JSONArray jsonarray = new JSONArray(field.getValue().toString()); + for (int i = 0; i < jsonarray.length(); i++) { + JSONObject jsonObject = jsonarray.getJSONObject(i); + String id = jsonObject.get("id").toString(); + String label = jsonObject.getString("label"); + if (id != null && label != null) { + map.put(id, label); + } + } + } else if (field.getValue().toString().startsWith("{")) { + JSONObject jsonObject = new JSONObject(field.getValue().toString()); + String id = jsonObject.get("id").toString(); + String label = jsonObject.getString("label"); if (id != null && label != null) { map.put(id, label); } @@ -251,25 +266,46 @@ public class WordBuilder { Map exMap = mapper.readValue(field.getValue().toString(), new TypeReference>() { }); return exMap.get("label"); - } + }*/ } StringBuilder sb = new StringBuilder(); int index = 0; - for (Map.Entry entry : map.entrySet()) { - sb.append(entry.getValue()); - if (index != map.size() - 1) sb.append(", "); + for (Map map: mapList) { + if (!map.containsKey("label") && !map.containsKey("description")) { + logger.error("Value is missing the \"label\" and the \"description\" attributes"); + map.put("label", "unknown Name"); + } + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() != null && (entry.getKey().equals("label") || entry.getKey().equals("description"))) { + sb.append(entry.getValue().toString()); + } + } + if (index != mapList.size() - 1) sb.append(", "); index++; } return sb.toString(); } else if (comboboxType.equals("wordlist")) { - return field.getValue() != null ? field.getValue().toString() : ""; + WordListData wordListData = (WordListData) field.getData(); + if (wordListData.getOptions().isEmpty() && field.getValue() != null) { + logger.warn("World List has no values but the field has"); + return field.getValue().toString(); + } else if (field.getValue() != null){ + ComboBoxData.Option selectedOption = null; + for (ComboBoxData.Option option: wordListData.getOptions()) { + if (option.getValue().equals(field.getValue())) { + selectedOption = option; + } + } + return selectedOption != null ? selectedOption.getLabel() : field.getValue().toString(); + } + return ""; } } case "booleanDecision": if (field.getValue() != null && field.getValue().equals("true")) return "Yes"; else return "No"; case "radiobox": - return field.getValue().toString(); + return field.getValue() != null ? field.getValue().toString() : null; case "checkBox": CheckBoxData data = (CheckBoxData) field.getData(); if (field.getValue() == null || field.getValue().equals("false")) return null; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java index 45d53242b..c86294e74 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/xml/datasetProfileXml/ExportXmlBuilderDatasetProfile.java @@ -205,6 +205,7 @@ public class ExportXmlBuilderDatasetProfile { WordListData wordListDataObject = (WordListData) field.getData(); dataOut.setAttribute("label", wordListDataObject.getLabel()); dataOut.setAttribute("type", wordListDataObject.getType()); + dataOut.setAttribute("multiList", wordListDataObject.getMultiList().toString()); Element options = element.createElement("options"); wordListDataObject.getOptions().forEach(optionChildFor -> { Element optionChild = element.createElement("option"); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/json/JavaToJson.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/json/JavaToJson.java new file mode 100644 index 000000000..8338c1526 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/json/JavaToJson.java @@ -0,0 +1,13 @@ +package eu.eudat.logic.utilities.json; + +public class JavaToJson { + + public static String objectStringToJson(String object) { + String result = object.replaceAll("=", "\":\"") + .replaceAll("\\{", "{\"") + .replaceAll(", ", "\", \"") + .replaceAll("}", "\"}" ). + replaceAll("}\", \"\\{", "}, {"); + return result; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java index 5272795e3..e4e5fcf94 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/AutoCompleteData.java @@ -129,6 +129,9 @@ public class AutoCompleteData extends ComboBoxData { this.multiAutoComplete = (Boolean) ((Map) data).get("multiAutoComplete"); List> dataList = (List>) ((Map) data).get("autocompleteSingle"); + if (dataList == null) { + dataList = (List>) ((Map) data).get("autoCompleteSingleDataList"); + } this.autoCompleteSingleDataList = new ArrayList<>(); @@ -174,19 +177,21 @@ public class AutoCompleteData extends ComboBoxData { List> autoCompletes = new ArrayList<>(); NodeList autoCompleteSingles = item.getChildNodes(); for (int i = 0; i < autoCompleteSingles.getLength(); i++) { - if (autoCompleteSingles.item(i) instanceof Element && !((Element) autoCompleteSingles.item(i)).getTagName().equals("option")) { - Element node = (Element) autoCompleteSingles.item(i); - if (!node.hasChildNodes()) { - node.appendChild(node); - } + if (autoCompleteSingles.item(i) instanceof Element) { + if (!((Element) autoCompleteSingles.item(i)).getTagName().equals("option")) { + Element node = (Element) autoCompleteSingles.item(i); + if (!node.hasChildNodes()) { + node.appendChild(node); + } - autoCompletes.add(singleToMap(node)); - } else if (((Element) autoCompleteSingles.item(i)).getTagName().equals("option")) { - Element node = item.getOwnerDocument().createElement("autocompleteSingle"); - node.appendChild(autoCompleteSingles.item(i)); - node.setAttribute("url", item.getAttribute("url")); - node.setAttribute("optionsRoot", item.getAttribute("optionsRoot")); - autoCompletes.add(singleToMap(node)); + autoCompletes.add(singleToMap(node)); + } else { + Element node = item.getOwnerDocument().createElement("autocompleteSingle"); + node.appendChild(autoCompleteSingles.item(i)); + node.setAttribute("url", item.getAttribute("url")); + node.setAttribute("optionsRoot", item.getAttribute("optionsRoot")); + autoCompletes.add(singleToMap(node)); + } } } dataMap.put("autocompleteSingle", autoCompletes); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/WordListData.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/WordListData.java index 69b4ca4b1..51cd7f840 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/WordListData.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/components/commons/datafield/WordListData.java @@ -12,6 +12,7 @@ import java.util.Map; public class WordListData extends ComboBoxData { private List