repository-deposit-ckan/src/main/java/eu/eudat/depositinterface/ckanrepository/interfaces/CkanDeposit.java

216 lines
10 KiB
Java

package eu.eudat.depositinterface.ckanrepository.interfaces;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.depositinterface.ckanrepository.config.CkanConfig;
import eu.eudat.depositinterface.ckanrepository.config.ConfigLoader;
import eu.eudat.depositinterface.models.DMPDepositModel;
import eu.eudat.depositinterface.models.FileEnvelope;
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.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.stereotype.Component;
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.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class CkanDeposit implements RepositoryDeposit {
private static final Logger logger = LoggerFactory.getLogger(CkanDeposit.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
private final ConfigLoader configLoader;
private final Environment environment;
@Autowired
public CkanDeposit(ConfigLoader configLoader, Environment environment){
this.configLoader = configLoader;
this.environment = environment;
}
@Override
public String deposit(String repositoryId, DMPDepositModel dmpDepositModel, String repositoryAccessToken) throws Exception {
CkanConfig ckanConfig = this.configLoader.getCkanConfig().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(ckanConfig != null) {
String doi;
CkanDataset dataset = new CkanDataset();
dataset.setName(dmpDepositModel.getLabel().replaceAll("[^a-zA-Z0-9]+", "_").toLowerCase());
//dataset.setPrivate(!dmpDepositModel.isPublic());
dataset.setPrivate(true);
dataset.setNotes(dmpDepositModel.getDescription());
dataset.setVersion(String.valueOf(dmpDepositModel.getVersion()));
dataset.setOwner_org(ckanConfig.getOrganization());
dataset.setAuthor("Argos User");
dataset.setAuthor_email("argosUser@example.com");
if (dmpDepositModel.getPreviousDOI() == null || dmpDepositModel.getPreviousDOI().isEmpty()) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", ckanConfig.getApiToken());
headers.setContentType(MediaType.APPLICATION_JSON);
String url = ckanConfig.getRepositoryUrl() + "package_create";
Object response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(dataset, headers), Object.class).getBody();
Map<String, Object> respMap = objectMapper.convertValue(response, Map.class);
respMap = (Map<String, Object>) respMap.get("result");
String id = String.valueOf(respMap.get("id"));
doi = String.valueOf(respMap.get("doi"));
this.uploadFiles(ckanConfig, dmpDepositModel, id);
} else {
JsonNode datasetJson = this.getDatasetIdentifier(ckanConfig, dmpDepositModel.getPreviousDOI()).get(0);
String datasetId = datasetJson.get("id").asText();
String version = datasetJson.get("version").asText();
JsonNode files = datasetJson.get("resources");
if (files.isArray()) {
for (JsonNode file : files) {
String fileId = file.get("id").asText();
this.deleteFile(ckanConfig, fileId);
}
}
this.uploadFiles(ckanConfig, dmpDepositModel, datasetId);
Map<String, Object> resp = this.updateVersion(ckanConfig, datasetId, version);
doi = (String) resp.get("doi");
}
return doi;
}
return null;
}
private Map<String, Object> updateVersion(CkanConfig ckanConfig, String datasetId, String version){
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", ckanConfig.getApiToken());
headers.setContentType(MediaType.APPLICATION_JSON);
String serverUrl = ckanConfig.getRepositoryUrl() + "package_patch";
Map<String, String> body = new HashMap<>();
body.put("id", datasetId);
body.put("version", String.valueOf(Integer.parseInt(version) + 1));
RestTemplate restTemplate = new RestTemplate();
return (Map<String, Object>)restTemplate.exchange(serverUrl, HttpMethod.POST, new HttpEntity<>(body, headers), Map.class).getBody().get("result");
}
private void deleteFile(CkanConfig ckanConfig, String fileId){
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", ckanConfig.getApiToken());
headers.setContentType(MediaType.APPLICATION_JSON);
String serverUrl = ckanConfig.getRepositoryUrl() + "resource_delete";
Map<String, String> map = new HashMap<>();
map.put("id", fileId);
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange(serverUrl, HttpMethod.POST, new HttpEntity<>(map, headers), Object.class);
}
private void uploadFiles(CkanConfig ckanConfig, DMPDepositModel dmpDepositModel, String id) throws IOException {
this.uploadFile(ckanConfig, dmpDepositModel.getPdfFile().getFilename(), dmpDepositModel.getPdfFile().getFile(), id);
FileEnvelope rdaJsonEnvelope = dmpDepositModel.getRdaJsonFile();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentLength(rdaJsonEnvelope.getFile().length());
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
responseHeaders.set("Content-Disposition", "attachment;filename=" + rdaJsonEnvelope.getFilename());
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
byte[] content = Files.readAllBytes(rdaJsonEnvelope.getFile().toPath());
ResponseEntity<byte[]> jsonFile = new ResponseEntity<>(content, responseHeaders, HttpStatus.OK);
String contentDisposition = jsonFile.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(jsonFile.getBody()));
output.flush();
output.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
this.uploadFile(ckanConfig, jsonFileName, rdaJson, id);
Files.deleteIfExists(rdaJson.toPath());
if(dmpDepositModel.getSupportingFilesZip() != null) {
this.uploadFile(ckanConfig, dmpDepositModel.getSupportingFilesZip().getName(), dmpDepositModel.getSupportingFilesZip(), id);
}
}
private JsonNode getDatasetIdentifier(CkanConfig ckanConfig, String previousDOI) throws JsonProcessingException {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", ckanConfig.getApiToken());
String serverUrl = ckanConfig + "package_search?q=doi:" + previousDOI + "&include_private=True";
RestTemplate restTemplate = new RestTemplate();
Object response = restTemplate.exchange(serverUrl, HttpMethod.GET, new HttpEntity<>(headers), Map.class).getBody().get("result");
JsonNode jsonNode = objectMapper.readTree(new JSONObject((Map<String, Object>)response).toString());
return jsonNode.findValues("results").get(0);
}
private void uploadFile(CkanConfig ckanConfig, String filename, File file, String datasetId) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.set("Authorization", ckanConfig.getApiToken());
MultipartBodyBuilder multipartBodyBuilder = new MultipartBodyBuilder();
Resource resource = new FileSystemResource(file);
multipartBodyBuilder.part("upload", resource)
.header("filename", filename);
multipartBodyBuilder.part("name", filename);
multipartBodyBuilder.part("package_id", datasetId);
MultiValueMap<String, HttpEntity<?>> multipartBody = multipartBodyBuilder.build();
HttpEntity<MultiValueMap<String, HttpEntity<?>>> requestEntity = new HttpEntity<>(multipartBody, headers);
String serverUrl = ckanConfig.getRepositoryUrl() + "resource_create";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Object> resp = restTemplate.postForEntity(serverUrl, requestEntity, Object.class);
}
@Override
public List<RepositoryDepositConfiguration> getConfiguration() {
List<eu.eudat.depositinterface.ckanrepository.config.CkanConfig> ckanConfigs = this.configLoader.getCkanConfig();
return ckanConfigs.stream().map(CkanConfig::toRepoConfig).collect(Collectors.toList());
}
@Override
public String getLogo(String repositoryId) {
RepositoryDepositConfiguration conf = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(conf != null) {
if(conf.isHasLogo()){
byte[] logo = this.configLoader.getLogo(repositoryId);
return (logo != null && logo.length != 0) ? Base64.getEncoder().encodeToString(logo) : null;
}
}
return null;
}
@Override
public String authenticate(String repositoryId, String code) {
return null;
}
}