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.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.*; @Component public class CkanDeposit implements RepositoryDeposit { private static final Logger logger = LoggerFactory.getLogger(CkanDeposit.class); private static final ObjectMapper objectMapper = new ObjectMapper(); private ConfigLoader configLoader; private Environment environment; @Autowired public CkanDeposit(ConfigLoader configLoader, Environment environment){ this.configLoader = configLoader; this.environment = environment; } @Override public String deposit(DMPDepositModel dmpDepositModel, String repositoryAccessToken) throws Exception { CkanConfig ckanConfig = this.configLoader.getCkanConfig(); 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 respMap = objectMapper.convertValue(response, Map.class); respMap = (Map) respMap.get("result"); String id = String.valueOf(respMap.get("id")); doi = String.valueOf(respMap.get("doi")); this.uploadFiles(dmpDepositModel, id); } else{ JsonNode datasetJson = this.getDatasetIdentifier(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(fileId); } } this.uploadFiles(dmpDepositModel, datasetId); Map resp = this.updateVersion(datasetId, version); doi = (String) resp.get("doi"); } return doi; } private Map updateVersion(String datasetId, String version){ HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", this.configLoader.getCkanConfig().getApiToken()); headers.setContentType(MediaType.APPLICATION_JSON); String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "package_patch"; Map body = new HashMap<>(); body.put("id", datasetId); body.put("version", String.valueOf(Integer.parseInt(version) + 1)); RestTemplate restTemplate = new RestTemplate(); return (Map)restTemplate.exchange(serverUrl, HttpMethod.POST, new HttpEntity<>(body, headers), Map.class).getBody().get("result"); } private void deleteFile(String fileId){ HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", this.configLoader.getCkanConfig().getApiToken()); headers.setContentType(MediaType.APPLICATION_JSON); String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "resource_delete"; Map 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(DMPDepositModel dmpDepositModel, String id) throws IOException { this.uploadFile(dmpDepositModel.getPdfFileName(), dmpDepositModel.getPdfFile(), id); 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, id); Files.deleteIfExists(rdaJson.toPath()); if(dmpDepositModel.getSupportingFilesZip() != null) { this.uploadFile(dmpDepositModel.getSupportingFilesZip().getName(), dmpDepositModel.getSupportingFilesZip(), id); } } private JsonNode getDatasetIdentifier(String previousDOI) throws JsonProcessingException { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", this.configLoader.getCkanConfig().getApiToken()); String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "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)response).toString()); return jsonNode.findValues("results").get(0); } private void uploadFile(String filename, File file, String datasetId) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); headers.set("Authorization", this.configLoader.getCkanConfig().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> multipartBody = multipartBodyBuilder.build(); HttpEntity>> requestEntity = new HttpEntity<>(multipartBody, headers); String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "resource_create"; RestTemplate restTemplate = new RestTemplate(); ResponseEntity resp = restTemplate.postForEntity(serverUrl, requestEntity, Object.class); } @Override public RepositoryDepositConfiguration getConfiguration() { eu.eudat.depositinterface.ckanrepository.config.CkanConfig ckanConfig = this.configLoader.getCkanConfig(); return ckanConfig.toRepoConfig(); } @Override public String getLogo() { RepositoryDepositConfiguration conf = this.getConfiguration(); if(conf.isHasLogo()){ byte[] logo = this.configLoader.getLogo(); return (logo != null && logo.length != 0) ? Base64.getEncoder().encodeToString(logo) : null; } return null; } @Override public String authenticate(String code) { return null; } }