2020-06-18 11:22:58 +02:00
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
package eu.dnetlib.dhp.common.api;
|
2020-06-18 11:19:20 +02:00
|
|
|
|
|
|
|
import java.io.*;
|
2020-06-18 11:22:58 +02:00
|
|
|
import java.io.IOException;
|
2020-10-27 15:53:02 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2020-07-07 18:09:06 +02:00
|
|
|
|
2021-08-11 12:13:22 +02:00
|
|
|
import org.apache.http.HttpHeaders;
|
|
|
|
import org.apache.http.entity.ContentType;
|
|
|
|
|
2020-06-18 11:34:15 +02:00
|
|
|
import com.google.gson.Gson;
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
import eu.dnetlib.dhp.common.api.zenodo.ZenodoModel;
|
|
|
|
import eu.dnetlib.dhp.common.api.zenodo.ZenodoModelList;
|
2020-07-07 18:09:06 +02:00
|
|
|
import okhttp3.*;
|
2020-06-19 17:39:46 +02:00
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
public class ZenodoAPIClient implements Serializable {
|
|
|
|
|
2020-06-18 11:22:58 +02:00
|
|
|
String urlString;
|
|
|
|
String bucket;
|
2020-06-18 14:21:36 +02:00
|
|
|
|
2020-06-18 11:22:58 +02:00
|
|
|
String deposition_id;
|
2020-06-18 18:38:54 +02:00
|
|
|
String access_token;
|
2020-06-18 11:22:58 +02:00
|
|
|
|
2020-07-07 18:09:06 +02:00
|
|
|
public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
|
2020-07-02 16:01:34 +02:00
|
|
|
|
2020-07-07 18:09:06 +02:00
|
|
|
private static final MediaType MEDIA_TYPE_ZIP = MediaType.parse("application/zip");
|
2020-07-02 16:01:34 +02:00
|
|
|
|
2020-06-18 11:22:58 +02:00
|
|
|
public String getUrlString() {
|
|
|
|
return urlString;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setUrlString(String urlString) {
|
|
|
|
this.urlString = urlString;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getBucket() {
|
|
|
|
return bucket;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBucket(String bucket) {
|
|
|
|
this.bucket = bucket;
|
|
|
|
}
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-09-07 11:40:16 +02:00
|
|
|
public void setDeposition_id(String deposition_id) {
|
|
|
|
this.deposition_id = deposition_id;
|
|
|
|
}
|
2020-08-07 16:44:51 +02:00
|
|
|
|
2021-08-11 12:13:22 +02:00
|
|
|
public ZenodoAPIClient(String urlString, String access_token) {
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-06-18 11:22:58 +02:00
|
|
|
this.urlString = urlString;
|
2020-06-18 18:38:54 +02:00
|
|
|
this.access_token = access_token;
|
2020-06-18 11:22:58 +02:00
|
|
|
}
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
/**
|
|
|
|
* Brand new deposition in Zenodo. It sets the deposition_id and the bucket where to store the files to upload
|
2020-10-27 17:31:33 +01:00
|
|
|
*
|
2020-08-07 16:44:51 +02:00
|
|
|
* @return response code
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
|
|
|
public int newDeposition() throws IOException {
|
2020-06-18 11:22:58 +02:00
|
|
|
String json = "{}";
|
2020-10-27 17:31:33 +01:00
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(600, TimeUnit.SECONDS).build();
|
|
|
|
|
2020-10-27 17:46:19 +01:00
|
|
|
RequestBody body = RequestBody.create(json, MEDIA_TYPE_JSON);
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
Request request = new Request.Builder()
|
2020-07-07 18:09:06 +02:00
|
|
|
.url(urlString)
|
2021-08-11 12:13:22 +02:00
|
|
|
.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()) // add request headers
|
|
|
|
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + access_token)
|
2020-07-07 18:09:06 +02:00
|
|
|
.post(body)
|
|
|
|
.build();
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
2020-07-07 18:09:06 +02:00
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
// Get response body
|
|
|
|
json = response.body().string();
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-07-02 16:01:34 +02:00
|
|
|
ZenodoModel newSubmission = new Gson().fromJson(json, ZenodoModel.class);
|
|
|
|
this.bucket = newSubmission.getLinks().getBucket();
|
|
|
|
this.deposition_id = newSubmission.getId();
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-07-02 16:01:34 +02:00
|
|
|
return response.code();
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-07-02 16:01:34 +02:00
|
|
|
}
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-07-02 16:01:34 +02:00
|
|
|
}
|
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
/**
|
|
|
|
* Upload files in Zenodo.
|
2020-10-27 17:31:33 +01:00
|
|
|
*
|
2020-08-07 16:44:51 +02:00
|
|
|
* @param is the inputStream for the file to upload
|
|
|
|
* @param file_name the name of the file as it will appear on Zenodo
|
|
|
|
* @param len the size of the file
|
|
|
|
* @return the response code
|
|
|
|
*/
|
|
|
|
public int uploadIS(InputStream is, String file_name, long len) throws IOException {
|
2020-10-27 17:31:33 +01:00
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder()
|
2020-10-30 14:10:10 +01:00
|
|
|
.writeTimeout(600, TimeUnit.SECONDS)
|
|
|
|
.readTimeout(600, TimeUnit.SECONDS)
|
|
|
|
.connectTimeout(600, TimeUnit.SECONDS)
|
|
|
|
.build();
|
2020-06-18 11:19:20 +02:00
|
|
|
|
2020-07-02 16:01:34 +02:00
|
|
|
Request request = new Request.Builder()
|
2020-07-07 18:09:06 +02:00
|
|
|
.url(bucket + "/" + file_name)
|
2021-08-11 12:13:22 +02:00
|
|
|
.addHeader(HttpHeaders.CONTENT_TYPE, "application/zip") // add request headers
|
|
|
|
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + access_token)
|
2020-08-07 16:44:51 +02:00
|
|
|
.put(InputStreamRequestBody.create(MEDIA_TYPE_ZIP, is, len))
|
2020-07-07 18:09:06 +02:00
|
|
|
.build();
|
2020-06-22 17:20:07 +02:00
|
|
|
|
2020-07-02 16:01:34 +02:00
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
2020-07-07 18:09:06 +02:00
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
2020-07-02 16:01:34 +02:00
|
|
|
return response.code();
|
|
|
|
}
|
2020-08-05 14:18:25 +02:00
|
|
|
}
|
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
/**
|
|
|
|
* Associates metadata information to the current deposition
|
2020-10-27 17:31:33 +01:00
|
|
|
*
|
2020-08-07 16:44:51 +02:00
|
|
|
* @param metadata the metadata
|
|
|
|
* @return response code
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
2020-07-02 16:01:34 +02:00
|
|
|
public int sendMretadata(String metadata) throws IOException {
|
|
|
|
|
2020-10-27 17:31:33 +01:00
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(600, TimeUnit.SECONDS).build();
|
2020-07-02 16:01:34 +02:00
|
|
|
|
2020-10-27 17:46:19 +01:00
|
|
|
RequestBody body = RequestBody.create(metadata, MEDIA_TYPE_JSON);
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
Request request = new Request.Builder()
|
2020-07-07 18:09:06 +02:00
|
|
|
.url(urlString + "/" + deposition_id)
|
2021-08-11 12:13:22 +02:00
|
|
|
.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()) // add request headers
|
|
|
|
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + access_token)
|
2020-07-07 18:09:06 +02:00
|
|
|
.put(body)
|
|
|
|
.build();
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
2020-07-07 18:09:06 +02:00
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
return response.code();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
/**
|
|
|
|
* To publish the current deposition. It works for both new deposition or new version of an old deposition
|
2020-10-27 17:31:33 +01:00
|
|
|
*
|
2020-08-11 14:17:31 +02:00
|
|
|
* @return response code
|
2020-08-07 16:44:51 +02:00
|
|
|
* @throws IOException
|
|
|
|
*/
|
2020-07-02 16:01:34 +02:00
|
|
|
public int publish() throws IOException {
|
|
|
|
|
|
|
|
String json = "{}";
|
|
|
|
|
2020-10-27 17:31:33 +01:00
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(600, TimeUnit.SECONDS).build();
|
2020-07-02 16:01:34 +02:00
|
|
|
|
2020-10-27 17:46:19 +01:00
|
|
|
RequestBody body = RequestBody.create(json, MEDIA_TYPE_JSON);
|
|
|
|
|
2020-07-02 16:01:34 +02:00
|
|
|
Request request = new Request.Builder()
|
2020-07-07 18:09:06 +02:00
|
|
|
.url(urlString + "/" + deposition_id + "/actions/publish")
|
|
|
|
.addHeader("Authorization", "Bearer " + access_token)
|
2020-10-30 14:10:10 +01:00
|
|
|
.post(body)
|
2020-07-07 18:09:06 +02:00
|
|
|
.build();
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
2020-07-07 18:09:06 +02:00
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
2020-07-02 16:01:34 +02:00
|
|
|
|
|
|
|
return response.code();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
/**
|
2020-10-27 17:31:33 +01:00
|
|
|
* To create a new version of an already published deposition. It sets the deposition_id and the bucket to be used
|
|
|
|
* for the new version.
|
|
|
|
*
|
|
|
|
* @param concept_rec_id the concept record id of the deposition for which to create a new version. It is the last
|
|
|
|
* part of the url for the DOI Zenodo suggests to use to cite all versions: DOI: 10.xxx/zenodo.656930
|
|
|
|
* concept_rec_id = 656930
|
2020-08-07 16:44:51 +02:00
|
|
|
* @return response code
|
|
|
|
* @throws IOException
|
|
|
|
* @throws MissingConceptDoiException
|
|
|
|
*/
|
|
|
|
public int newVersion(String concept_rec_id) throws IOException, MissingConceptDoiException {
|
2022-06-08 17:03:15 +02:00
|
|
|
setDepositionId(concept_rec_id, 1);
|
2020-08-07 16:44:51 +02:00
|
|
|
String json = "{}";
|
|
|
|
|
2020-10-27 17:31:33 +01:00
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(600, TimeUnit.SECONDS).build();
|
2020-08-07 16:44:51 +02:00
|
|
|
|
2020-10-27 17:46:19 +01:00
|
|
|
RequestBody body = RequestBody.create(json, MEDIA_TYPE_JSON);
|
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
Request request = new Request.Builder()
|
2020-09-07 11:40:16 +02:00
|
|
|
.url(urlString + "/" + deposition_id + "/actions/newversion")
|
2021-08-11 12:13:22 +02:00
|
|
|
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + access_token)
|
2020-10-30 14:10:10 +01:00
|
|
|
.post(body)
|
2020-09-07 11:40:16 +02:00
|
|
|
.build();
|
2020-08-07 16:44:51 +02:00
|
|
|
|
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
|
|
|
|
|
|
|
ZenodoModel zenodoModel = new Gson().fromJson(response.body().string(), ZenodoModel.class);
|
|
|
|
String latest_draft = zenodoModel.getLinks().getLatest_draft();
|
|
|
|
deposition_id = latest_draft.substring(latest_draft.lastIndexOf("/") + 1);
|
|
|
|
bucket = getBucket(latest_draft);
|
|
|
|
return response.code();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-05 16:30:36 +01:00
|
|
|
/**
|
|
|
|
* To finish uploading a version or new deposition not published
|
|
|
|
* It sets the deposition_id and the bucket to be used
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @param deposition_id the deposition id of the not yet published upload
|
|
|
|
* concept_rec_id = 656930
|
|
|
|
* @return response code
|
|
|
|
* @throws IOException
|
|
|
|
* @throws MissingConceptDoiException
|
|
|
|
*/
|
2020-10-27 17:31:33 +01:00
|
|
|
public int uploadOpenDeposition(String deposition_id) throws IOException, MissingConceptDoiException {
|
|
|
|
|
|
|
|
this.deposition_id = deposition_id;
|
|
|
|
|
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(600, TimeUnit.SECONDS).build();
|
|
|
|
|
|
|
|
Request request = new Request.Builder()
|
|
|
|
.url(urlString + "/" + deposition_id)
|
|
|
|
.addHeader("Authorization", "Bearer " + access_token)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
|
|
|
|
|
|
|
ZenodoModel zenodoModel = new Gson().fromJson(response.body().string(), ZenodoModel.class);
|
|
|
|
bucket = zenodoModel.getLinks().getBucket();
|
|
|
|
return response.code();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-06-08 17:03:15 +02:00
|
|
|
private void setDepositionId(String concept_rec_id, Integer page) throws IOException, MissingConceptDoiException {
|
2020-08-07 16:44:51 +02:00
|
|
|
|
2022-07-01 10:44:08 +02:00
|
|
|
ZenodoModelList zenodoModelList = new Gson()
|
|
|
|
.fromJson(getPrevDepositions(String.valueOf(page)), ZenodoModelList.class);
|
2020-08-07 16:44:51 +02:00
|
|
|
|
2020-09-07 11:40:16 +02:00
|
|
|
for (ZenodoModel zm : zenodoModelList) {
|
|
|
|
if (zm.getConceptrecid().equals(concept_rec_id)) {
|
|
|
|
deposition_id = zm.getId();
|
2020-08-07 16:44:51 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2022-07-01 10:44:08 +02:00
|
|
|
if (zenodoModelList.size() == 0)
|
|
|
|
throw new MissingConceptDoiException(
|
|
|
|
"The concept record id specified was missing in the list of depositions");
|
2022-06-08 17:03:15 +02:00
|
|
|
setDepositionId(concept_rec_id, page + 1);
|
2020-08-07 16:44:51 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-06-08 17:03:15 +02:00
|
|
|
private String getPrevDepositions(String page) throws IOException {
|
|
|
|
|
2020-10-27 17:31:33 +01:00
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(600, TimeUnit.SECONDS).build();
|
2020-08-07 16:44:51 +02:00
|
|
|
|
2022-06-08 17:03:15 +02:00
|
|
|
HttpUrl.Builder urlBuilder = HttpUrl.parse(urlString).newBuilder();
|
|
|
|
urlBuilder.addQueryParameter("page", page);
|
|
|
|
String url = urlBuilder.build().toString();
|
|
|
|
|
2020-08-07 16:44:51 +02:00
|
|
|
Request request = new Request.Builder()
|
2022-07-01 10:44:08 +02:00
|
|
|
.url(url)
|
|
|
|
.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()) // add request headers
|
|
|
|
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + access_token)
|
|
|
|
.get()
|
|
|
|
.build();
|
2020-08-07 16:44:51 +02:00
|
|
|
|
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
|
|
|
|
|
|
|
return response.body().string();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private String getBucket(String url) throws IOException {
|
2020-10-27 17:31:33 +01:00
|
|
|
OkHttpClient httpClient = new OkHttpClient.Builder()
|
2020-10-30 14:10:10 +01:00
|
|
|
.connectTimeout(600, TimeUnit.SECONDS)
|
|
|
|
.build();
|
2020-08-07 16:44:51 +02:00
|
|
|
|
|
|
|
Request request = new Request.Builder()
|
2020-09-07 11:40:16 +02:00
|
|
|
.url(url)
|
2021-08-11 12:13:22 +02:00
|
|
|
.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()) // add request headers
|
|
|
|
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + access_token)
|
2020-09-07 11:40:16 +02:00
|
|
|
.get()
|
|
|
|
.build();
|
2020-08-07 16:44:51 +02:00
|
|
|
|
|
|
|
try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
|
|
|
if (!response.isSuccessful())
|
|
|
|
throw new IOException("Unexpected code " + response + response.body().string());
|
|
|
|
|
|
|
|
// Get response body
|
|
|
|
ZenodoModel zenodoModel = new Gson().fromJson(response.body().string(), ZenodoModel.class);
|
|
|
|
|
|
|
|
return zenodoModel.getLinks().getBucket();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-06-18 11:19:20 +02:00
|
|
|
}
|