argos/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java

201 lines
9.4 KiB
Java

package eu.eudat.depositinterface.dataverserepository.interfaces;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.researchspace.dataverse.api.v1.DataverseAPI;
import com.researchspace.dataverse.api.v1.DataverseConfig;
import com.researchspace.dataverse.entities.*;
import com.researchspace.dataverse.entities.facade.DatasetAuthor;
import com.researchspace.dataverse.entities.facade.DatasetContact;
import com.researchspace.dataverse.entities.facade.DatasetDescription;
import com.researchspace.dataverse.entities.facade.DatasetFacade;
import com.researchspace.dataverse.http.DataverseAPIImpl;
import eu.eudat.depositinterface.dataverserepository.config.ConfigLoader;
import eu.eudat.depositinterface.models.DMPDepositModel;
import eu.eudat.depositinterface.repository.RepositoryDeposit;
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;
import static com.researchspace.dataverse.entities.Version.MAJOR;
import static com.researchspace.dataverse.entities.Version.MINOR;
@Component
public class DataverseDeposit implements RepositoryDeposit {
private static final Logger logger = LoggerFactory.getLogger(DataverseDeposit.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
private DataverseAPI api;
private boolean isApiSet;
private ConfigLoader configLoader;
private Environment environment;
@Autowired
public DataverseDeposit(ConfigLoader configLoader, Environment environment){
this.configLoader = configLoader;
this.environment = environment;
this.isApiSet = false;
}
private void setDataverseApi() throws MalformedURLException {
if(!this.isApiSet) {
this.api = new DataverseAPIImpl();
eu.eudat.depositinterface.dataverserepository.config.DataverseConfig jsonConfig = this.configLoader.getDataverseConfig();
DataverseConfig config = new DataverseConfig(new URL(jsonConfig.getServer()), jsonConfig.getApiToken(), jsonConfig.getParentDataverseAlias());
api.configure(config);
this.isApiSet = true;
}
}
@Override
public String deposit(DMPDepositModel dmpDepositModel, String repositoryAccessToken) throws Exception {
if(!this.isApiSet)
this.setDataverseApi();
String doi;
DatasetFacade dataset = DatasetFacade.builder()
.title(dmpDepositModel.getLabel())
.authors(dmpDepositModel.getUsers().stream().map(x -> DatasetAuthor.builder().authorName(x.getUser().getName()).build()).collect(Collectors.toList()))
.contacts(dmpDepositModel.getUsers().stream().map(x -> DatasetContact.builder().datasetContactEmail(x.getUser().getEmail()).build()).collect(Collectors.toList()))
.subject("Other")
.description(DatasetDescription.builder().description(dmpDepositModel.getDescription()).build())
.languages(new ArrayList<>())
.depositor("")
.build();
if(dmpDepositModel.getPreviousDOI() == null || dmpDepositModel.getPreviousDOI().isEmpty()){
Identifier id = this.api.getDataverseOperations().createDataset(dataset, this.configLoader.getDataverseConfig().getParentDataverseAlias());
doi = this.api.getDatasetOperations().getDataset(id).getDoiId().orElse(null);
this.uploadFiles(dmpDepositModel, doi);
this.api.getDatasetOperations().publishDataset(id, MAJOR);
}
else{
Map<String, Object> datasetJson = this.getDatasetIdentifier(dmpDepositModel.getPreviousDOI());
Identifier id = new Identifier();
id.setId(((Integer) datasetJson.get("id")).longValue());
JsonNode jsonNode = this.objectMapper.readTree(new JSONObject(datasetJson).toString());
List<JsonNode> files = jsonNode.findValues("dataFile");
for(JsonNode file: files){
int fileId = file.get("id").asInt();
this.deleteFile(fileId);
}
this.uploadFiles(dmpDepositModel, dmpDepositModel.getPreviousDOI());
this.api.getDatasetOperations().updateDataset(dataset, id);
DataverseResponse<PublishedDataset> publishedDataset = this.api.getDatasetOperations().publishDataset(id, MAJOR);
doi = publishedDataset.getData().getAuthority() + "/" + publishedDataset.getData().getIdentifier();
}
return doi;
}
private void deleteFile(int fileId){
HttpHeaders headers = this.createBasicAuthHeaders(this.configLoader.getDataverseConfig().getApiToken(), "");
String serverUrl = this.configLoader.getDataverseConfig().getServer() + "/dvn/api/data-deposit/v1.1/swordv2/edit-media/file/" + fileId;
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange(serverUrl, HttpMethod.DELETE, new HttpEntity<>(headers), Object.class);
}
private HttpHeaders createBasicAuthHeaders(String username, String password) {
return new HttpHeaders() {{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.getEncoder().encode(
auth.getBytes(StandardCharsets.UTF_8));
String authHeader = "Basic " + new String(encodedAuth);
set("Authorization", authHeader);
}};
}
private void uploadFiles(DMPDepositModel dmpDepositModel, String doi) throws IOException {
this.uploadFile(dmpDepositModel.getPdfFileName(), dmpDepositModel.getPdfFile(), doi);
String contentDisposition = dmpDepositModel.getRdaJson().getHeaders().get("Content-Disposition").get(0);
String jsonFileName = contentDisposition.substring(contentDisposition.lastIndexOf('=') + 1);
File rdaJson = new File(this.environment.getProperty("storage.temp") + jsonFileName);
OutputStream output = new FileOutputStream(rdaJson);
try {
output.write(Objects.requireNonNull(dmpDepositModel.getRdaJson().getBody()));
output.flush();
output.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
this.uploadFile(jsonFileName, rdaJson, doi);
Files.deleteIfExists(rdaJson.toPath());
if(dmpDepositModel.getSupportingFilesZip() != null) {
this.uploadFile(dmpDepositModel.getSupportingFilesZip().getName(), dmpDepositModel.getSupportingFilesZip(), doi);
}
}
private Map<String, Object> getDatasetIdentifier(String previousDOI) {
HttpHeaders headers = new HttpHeaders();
headers.set("X-Dataverse-key", this.configLoader.getDataverseConfig().getApiToken());
String serverUrl = this.configLoader.getDataverseConfig().getServer() + "/api/datasets/:persistentId?persistentId=doi:" + previousDOI;
RestTemplate restTemplate = new RestTemplate();
return (Map<String, Object>) restTemplate.exchange(serverUrl, HttpMethod.GET, new HttpEntity<>(headers), Map.class).getBody().get("data");
}
private void uploadFile(String filename, File file, String doi) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.set("X-Dataverse-key", this.configLoader.getDataverseConfig().getApiToken());
MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
ContentDisposition contentDisposition = ContentDisposition
.builder("form-data")
.name("file")
.filename(filename)
.build();
fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
HttpEntity<byte[]> fileEntity = new HttpEntity<>(Files.readAllBytes(file.toPath()), fileMap);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", fileEntity);
body.add("jsonData", "{\"restrict\":\"false\", \"tabIngest\":\"false\"}");
HttpEntity<MultiValueMap<String, Object>> requestEntity
= new HttpEntity<>(body, headers);
String serverUrl = this.configLoader.getDataverseConfig().getServer() + "/api/datasets/:persistentId/add?persistentId=doi:" + doi;
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Object> resp = restTemplate.postForEntity(serverUrl, requestEntity, Object.class);
}
@Override
public RepositoryDepositConfiguration getConfiguration() {
eu.eudat.depositinterface.dataverserepository.config.DataverseConfig dataverseConfig = this.configLoader.getDataverseConfig();
return dataverseConfig.toRepoConfig();
}
@Override
public String authenticate(String code) {
return null;
}
}