diff --git a/.github/linters/sun_checks.xml b/.github/linters/sun_checks.xml
index d2ec5e6..74766cb 100644
--- a/.github/linters/sun_checks.xml
+++ b/.github/linters/sun_checks.xml
@@ -118,12 +118,14 @@
-
+
@@ -178,13 +180,13 @@
-
diff --git a/src/main/java/eosc/eu/ActionError.java b/src/main/java/eosc/eu/ActionError.java
index 40eefa2..b315a5c 100644
--- a/src/main/java/eosc/eu/ActionError.java
+++ b/src/main/java/eosc/eu/ActionError.java
@@ -14,6 +14,7 @@
import javax.ws.rs.core.Response.Status;
import parser.b2share.B2ShareException;
+import parser.esrf.EsrfException;
import parser.zenodo.ZenodoException;
import egi.fts.FileTransferServiceException;
@@ -48,6 +49,7 @@ public class ActionError {
/**
* Copy constructor does deep copy
+ * @param error Error to copy
*/
public ActionError(ActionError error) {
@@ -67,6 +69,8 @@ public ActionError(ActionError error) {
/**
* Copy but change id
+ * @param error Error to copy
+ * @param newId New error id
*/
public ActionError(ActionError error, String newId) {
this(error);
@@ -75,6 +79,7 @@ public ActionError(ActionError error, String newId) {
/**
* Construct with error id
+ * @param id Error id
*/
public ActionError(String id) {
this.id = id;
@@ -84,6 +89,8 @@ public ActionError(String id) {
/**
* Construct with error id and description
+ * @param id Error id
+ * @param description Error description
*/
public ActionError(String id, String description) {
this.id = id;
@@ -93,6 +100,8 @@ public ActionError(String id, String description) {
/**
* Construct with error id and detail
+ * @param id Error id
+ * @param detail Key-value pair to add to the details of the error
*/
public ActionError(String id, Tuple2 detail) {
this(id, Arrays.asList(detail));
@@ -100,6 +109,8 @@ public ActionError(String id, Tuple2 detail) {
/**
* Construct with error id and details
+ * @param id Error id
+ * @param details Key-value pairs to add to the details of the error
*/
public ActionError(String id, List> details) {
this.id = id;
@@ -115,6 +126,9 @@ public ActionError(String id, List> details) {
/**
* Construct with error id, description, and detail
+ * @param id Error id
+ * @param description Error description
+ * @param detail Key-value pair to add to the details of the error
*/
public ActionError(String id, String description, Tuple2 detail) {
this(id, description, Arrays.asList(detail));
@@ -122,6 +136,9 @@ public ActionError(String id, String description, Tuple2 detail)
/**
* Construct with error id, description, and details
+ * @param id Error id
+ * @param description Error description
+ * @param details Key-value pairs to add to the details of the error
*/
public ActionError(String id, String description, List> details) {
this.id = id;
@@ -137,6 +154,7 @@ public ActionError(String id, String description, List> d
/**
* Construct from exception
+ * @param t The exception to wrap
*/
public ActionError(Throwable t) {
this.id = "exception";
@@ -151,6 +169,7 @@ public ActionError(Throwable t) {
var type = t.getClass();
if (type.equals(ZenodoException.class) ||
type.equals(B2ShareException.class) ||
+ type.equals(EsrfException.class) ||
type.equals(FileTransferServiceException.class) ||
type.equals(ClientWebApplicationException.class) ||
type.equals(WebApplicationException.class) ) {
@@ -217,6 +236,8 @@ else if(type.equals(ProcessingException.class)) {
/**
* Construct from exception and detail
+ * @param t The exception to wrap
+ * @param detail Key-value pair to add to the details of the error
*/
public ActionError(Throwable t, Tuple2 detail) {
this(t, Arrays.asList(detail));
@@ -224,6 +245,8 @@ public ActionError(Throwable t, Tuple2 detail) {
/**
* Construct from exception and details
+ * @param t The exception to wrap
+ * @param details Key-value pair to add to the details of the error
*/
public ActionError(Throwable t, List> details) {
this(t);
@@ -265,6 +288,7 @@ else if(keys.contains("seUrl"))
/**
* Retrieve the HTTP status code
+ * @return HTTP status code
*/
public Status getStatus() {
return this.status;
@@ -272,6 +296,8 @@ public Status getStatus() {
/**
* Update the HTTP status code
+ * @param status New HTTP status
+ * @return Instance to allow for fluent calls (with .)
*/
public ActionError setStatus(Status status) {
this.status = status;
@@ -280,6 +306,7 @@ public ActionError setStatus(Status status) {
/**
* Convert to Response that can be returned by a REST endpoint
+ * @return Response object
*/
public Response toResponse() {
return Response.ok(this).status(this.status).build();
@@ -287,6 +314,8 @@ public Response toResponse() {
/**
* Convert to Response with new status that can be returned by a REST endpoint
+ * @param status New HTTP status
+ * @return Response object with new HTTP status code
*/
public Response toResponse(Status status) {
return Response.ok(this).status(status).build();
diff --git a/src/main/java/eosc/eu/model/StorageElement.java b/src/main/java/eosc/eu/model/StorageElement.java
index 891fade..23e9796 100644
--- a/src/main/java/eosc/eu/model/StorageElement.java
+++ b/src/main/java/eosc/eu/model/StorageElement.java
@@ -9,6 +9,7 @@
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import parser.zenodo.model.ZenodoFile;
import parser.b2share.model.B2ShareFile;
+import parser.esrf.model.EsrfDataFile;
import egi.fts.model.ObjectInfo;
@@ -55,7 +56,9 @@ public class StorageElement extends StorageElementBase {
public StorageElement() { super("StorageElement"); }
/**
- * Constructor
+ * Construct using access URL and media type
+ * @param url Access URL for the storage element
+ * @param type Media type
*/
public StorageElement(String url, String type) {
super("StorageElement");
@@ -65,6 +68,7 @@ public StorageElement(String url, String type) {
/**
* Construct from Zenodo file
+ * @param zf Zenodo file
*/
public StorageElement(ZenodoFile zf) {
super("StorageElement", zf.filename);
@@ -76,8 +80,27 @@ public StorageElement(ZenodoFile zf) {
}
}
+ /**
+ * Construct from ESRF file
+ * @param ef ESRF file
+ * @param baseUrl The base URL for the access URL, as the ESRF file
+ * only contains the path to the file
+ */
+ public StorageElement(EsrfDataFile ef, String baseUrl) {
+ super("StorageElement", ef.Datafile.name);
+ this.size = ef.Datafile.fileSize;
+ this.accessUrl = baseUrl + ef.Datafile.location;
+
+ if(null != ef.Datafile.createTime)
+ this.createdAt = ef.Datafile.createTime;
+
+ if(null != ef.Datafile.modTime)
+ this.modifiedAt = ef.Datafile.modTime;
+ }
+
/**
* Construct from B2Share file
+ * @param b2sf B2SHARE file
*/
public StorageElement(B2ShareFile b2sf) {
super("StorageElement", b2sf.name);
@@ -94,6 +117,7 @@ public StorageElement(B2ShareFile b2sf) {
/**
* Construct from FTS object
+ * @param obj Information about an object returned by FTS
*/
public StorageElement(ObjectInfo obj) {
super("StorageElement");
diff --git a/src/main/java/parser/b2share/B2ShareException.java b/src/main/java/parser/b2share/B2ShareException.java
index b69c12b..ff53527 100644
--- a/src/main/java/parser/b2share/B2ShareException.java
+++ b/src/main/java/parser/b2share/B2ShareException.java
@@ -15,10 +15,19 @@ public B2ShareException() {
super();
}
+ /***
+ * Construct from a response
+ * @param resp Response object
+ * @param body Response body
+ */
public B2ShareException(Response resp, String body) {
super(resp);
this.responseBody = body;
}
+ /***
+ * Get the response body
+ * @return Body of the response
+ */
String responseBody() { return responseBody; }
}
diff --git a/src/main/java/parser/b2share/B2ShareParser.java b/src/main/java/parser/b2share/B2ShareParser.java
index 1b2103a..0482087 100644
--- a/src/main/java/parser/b2share/B2ShareParser.java
+++ b/src/main/java/parser/b2share/B2ShareParser.java
@@ -37,6 +37,7 @@ public class B2ShareParser implements ParserService {
/***
* Constructor
+ * @param id The key of the parser in the config file
*/
public B2ShareParser(String id) { this.id = id; }
@@ -47,7 +48,6 @@ public class B2ShareParser implements ParserService {
* @return true on success
*/
public boolean init(ParserConfig config, PortConfig port) {
-
this.name = config.name();
this.timeout = config.timeout();
@@ -122,7 +122,8 @@ else if(!doi.equals(redirectedToUrl))
LOG.debugf("Redirected DOI %s", redirectedToUrl);
// Validate URL
- Pattern p = Pattern.compile("^(https?://[^/:]*b2share[^/:]*:?[\\d]*)/records/(.+)", Pattern.CASE_INSENSITIVE);
+ Pattern p = Pattern.compile("^(https?://[^/:]*b2share[^/:]*:?[\\d]*)/records/(.+)",
+ Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(redirectedToUrl);
boolean isSupported = m.matches();
diff --git a/src/main/java/parser/esrf/Esrf.java b/src/main/java/parser/esrf/Esrf.java
new file mode 100644
index 0000000..824a139
--- /dev/null
+++ b/src/main/java/parser/esrf/Esrf.java
@@ -0,0 +1,38 @@
+package parser.esrf;
+
+import io.smallrye.mutiny.Uni;
+import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+
+import org.jboss.resteasy.reactive.RestPath;
+import org.jboss.resteasy.reactive.RestQuery;
+import parser.esrf.model.*;
+
+import java.util.List;
+
+
+/***
+ * REST client for ESRF
+ */
+@RegisterProvider(value = EsrfExceptionMapper.class)
+@Produces(MediaType.APPLICATION_JSON)
+public interface Esrf {
+
+ @POST
+ @Path("/session")
+ @Consumes(MediaType.APPLICATION_JSON)
+ Uni getSessionAsync(EsrfCredentials credentials);
+
+ @GET
+ @Path("/doi/{authority}/{recordId}/datasets")
+ Uni> getDataSetsAsync(@RestQuery("sessionId") String sessionId,
+ @RestPath("authority") String authority,
+ @RestPath("recordId") String recordId);
+
+ @GET
+ @Path("/catalogue/{sessionId}/dataset/id/{datasetId}/datafile")
+ Uni> getDataFilesAsync(@RestPath("sessionId") String sessionId,
+ @RestPath("datasetId") String datasetId);
+}
diff --git a/src/main/java/parser/esrf/EsrfException.java b/src/main/java/parser/esrf/EsrfException.java
new file mode 100644
index 0000000..b04dd4d
--- /dev/null
+++ b/src/main/java/parser/esrf/EsrfException.java
@@ -0,0 +1,33 @@
+package parser.esrf;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+
+/**
+ * Exception class for ESRF API calls
+ */
+public class EsrfException extends WebApplicationException {
+
+ private String responseBody;
+
+ public EsrfException() {
+ super();
+ }
+
+ /***
+ * Construct from a response
+ * @param resp Response object
+ * @param body Response body
+ */
+ public EsrfException(Response resp, String body) {
+ super(resp);
+ this.responseBody = body;
+ }
+
+ /***
+ * Get the response body
+ * @return Body of the response
+ */
+ String responseBody() { return responseBody; }
+}
diff --git a/src/main/java/parser/esrf/EsrfExceptionMapper.java b/src/main/java/parser/esrf/EsrfExceptionMapper.java
new file mode 100644
index 0000000..cdb0077
--- /dev/null
+++ b/src/main/java/parser/esrf/EsrfExceptionMapper.java
@@ -0,0 +1,47 @@
+package parser.esrf;
+
+import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
+import org.jboss.resteasy.reactive.common.jaxrs.ResponseImpl;
+import static org.jboss.resteasy.reactive.RestResponse.StatusCode;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import java.io.ByteArrayInputStream;
+
+
+/**
+ * Custom exception mapper for ESRF API calls, allows access to response body in case of error
+ */
+@Priority(Priorities.USER)
+public final class EsrfExceptionMapper implements ResponseExceptionMapper {
+
+ @Override
+ public EsrfException toThrowable(Response response) {
+ try {
+ response.bufferEntity();
+ } catch(Exception ignored) {}
+
+ String msg = getBody(response);
+ return new EsrfException(response, msg);
+ }
+
+ @Override
+ public boolean handles(int status, MultivaluedMap headers) {
+ return status >= StatusCode.BAD_REQUEST;
+ }
+
+ private String getBody(Response response) {
+ String body = "";
+ if(response.hasEntity()) {
+ ByteArrayInputStream is = (ByteArrayInputStream)response.getEntity();
+ if(null == is)
+ is = (ByteArrayInputStream)((ResponseImpl)response).getEntityStream();
+ byte[] bytes = new byte[is.available()];
+ is.read(bytes, 0, is.available());
+ body = new String(bytes);
+ }
+ return body;
+ }
+}
diff --git a/src/main/java/parser/esrf/EsrfParser.java b/src/main/java/parser/esrf/EsrfParser.java
new file mode 100644
index 0000000..f00f956
--- /dev/null
+++ b/src/main/java/parser/esrf/EsrfParser.java
@@ -0,0 +1,223 @@
+package parser.esrf;
+
+import eosc.eu.PortConfig;
+import io.smallrye.mutiny.Uni;
+import io.smallrye.mutiny.tuples.Tuple2;
+import org.eclipse.microprofile.rest.client.RestClientBuilder;
+import org.eclipse.microprofile.rest.client.RestClientDefinitionException;
+import org.jboss.logging.Logger;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import eosc.eu.ParsersConfig.ParserConfig;
+import eosc.eu.ParserService;
+import eosc.eu.TransferServiceException;
+import eosc.eu.model.*;
+import parser.ParserHelper;
+import parser.esrf.model.EsrfCredentials;
+
+
+/***
+ * Class for parsing ESRF DOIs
+ */
+public class EsrfParser implements ParserService {
+
+ private static final Logger LOG = Logger.getLogger(EsrfParser.class);
+
+ private String id;
+ private String name;
+ private int timeout;
+ private String baseUrl;
+ private String authority;
+ private String recordId;
+ private static Esrf parser;
+
+
+ /***
+ * Constructor
+ * @param id The key of the parser in the config file
+ */
+ public EsrfParser(String id) { this.id = id; }
+
+ /***
+ * Initialize the REST client for ESRF.
+ * @param config Configuration of the parser, from the config file.
+ * @param port The port on which the application runs, from the config file.
+ * @return true on success
+ */
+ public boolean init(ParserConfig config, PortConfig port) {
+ this.name = config.name();
+ this.timeout = config.timeout();
+
+ if (null != parser)
+ return true;
+
+ LOG.debug("Obtaining REST client for ESRF");
+
+ // Check if base URL is valid
+ URL urlParserService;
+ try {
+ this.baseUrl = config.url().isPresent() ? config.url().get() : "";
+ urlParserService = new URL(this.baseUrl);
+
+ if(!this.baseUrl.isEmpty() && '/' == this.baseUrl.charAt(this.baseUrl.length() - 1))
+ this.baseUrl = this.baseUrl.replaceAll("[/]+$", "");
+
+ } catch (MalformedURLException e) {
+ LOG.error(e.getMessage());
+ return false;
+ }
+
+ try {
+ // Create the REST client for the parser service
+ parser = RestClientBuilder.newBuilder()
+ .baseUrl(urlParserService)
+ .build(Esrf.class);
+
+ return true;
+ }
+ catch (RestClientDefinitionException e) {
+ LOG.error(e.getMessage());
+ }
+
+ return false;
+ }
+
+ /***
+ * Get the Id of the parser.
+ * @return Id of the parser service.
+ */
+ public String getId() { return this.id; }
+
+ /***
+ * Get the human-readable name of the parser.
+ * @return Name of the parser service.
+ */
+ public String getName() { return this.name; }
+
+ /***
+ * Get the Id of the source record.
+ * @return Source record Id.
+ */
+ public String sourceId() { return this.recordId; }
+
+ /***
+ * Checks if the parser service understands this DOI.
+ * @param auth The access token needed to call the service.
+ * @param doi The DOI for a data set.
+ * @param helper Helper class that can follow (and cache) redirects.
+ * @return Return true if the parser service can parse this DOI.
+ */
+ public Uni> canParseDOI(String auth, String doi, ParserHelper helper) {
+ boolean isValid = null != doi && !doi.isBlank();
+ if(!isValid)
+ return Uni.createFrom().failure(new TransferServiceException("doiInvalid"));
+
+ // Check if DOI points/redirects to an ESRF record
+ var result = Uni.createFrom().item(helper.redirectedToUrl())
+
+ .chain(redirectedToUrl -> {
+ if(null != redirectedToUrl)
+ return Uni.createFrom().item(redirectedToUrl);
+
+ return helper.checkRedirect(doi);
+ })
+ .chain(redirectedToUrl -> {
+ if(null == redirectedToUrl)
+ redirectedToUrl = doi;
+ else if(!doi.equals(redirectedToUrl))
+ LOG.debugf("Redirected DOI %s", redirectedToUrl);
+
+ // Validate URL
+ Pattern p = Pattern.compile("^https?://([\\w\\.]*esrf.fr)/doi/([^/]+)/([^/#\\?]+)",
+ Pattern.CASE_INSENSITIVE);
+ Matcher m = p.matcher(redirectedToUrl);
+ boolean isSupported = m.matches();
+
+ if(isSupported) {
+ this.authority = m.group(2);
+ this.recordId = m.group(3);
+ }
+
+ return Uni.createFrom().item(Tuple2.of(isSupported, (ParserService)this));
+ })
+ .onFailure().invoke(e -> {
+ LOG.errorf("Failed to check if DOI %s points to ESRF record", doi);
+ });
+
+ return result;
+ }
+
+ /**
+ * Parse the DOI and return a set of files in the data set.
+ * @param auth The access token needed to call the service.
+ * @param doi The DOI for a data set.
+ * @param level Unused.
+ * @return List of files in the data set.
+ */
+ public Uni parseDOI(String auth, String doi, int level) {
+ if(null == doi || doi.isBlank())
+ return Uni.createFrom().failure(new TransferServiceException("doiInvalid"));
+
+ if(null == parser)
+ return Uni.createFrom().failure(new TransferServiceException("configInvalid"));
+
+ if(null == this.authority || this.authority.isEmpty() ||
+ null == this.recordId || this.recordId.isEmpty())
+ return Uni.createFrom().failure(new TransferServiceException("noRecordId"));
+
+ AtomicReference sessionId = new AtomicReference<>(null);
+ Uni result = Uni.createFrom().nullItem()
+
+ .ifNoItem()
+ .after(Duration.ofMillis(this.timeout))
+ .failWith(new TransferServiceException("doiParseTimeout"))
+ .chain(unused -> {
+ // Get an ESRF session
+ return parser.getSessionAsync(new EsrfCredentials("reader", "reader"));
+ })
+ .chain(session -> {
+ // Got a session
+ if(null == session || null == session.sessionId)
+ return Uni.createFrom().failure(new TransferServiceException("noSessionId"));
+
+ sessionId.set(session.sessionId);
+
+ // Get the dataset
+ return parser.getDataSetsAsync(sessionId.get(), this.authority, this.recordId);
+ })
+ .chain(datasets -> {
+ // Got dataset(s)
+ LOG.infof("Found %d datasets at DOI %s", datasets.size(), doi);
+
+ // Handle the first dataset, ignore the rest
+ var dataset = datasets.get(0);
+ LOG.infof("First dataset has ID %s", dataset.id);
+
+ return parser.getDataFilesAsync(sessionId.get(), dataset.id);
+ })
+ .chain(files -> {
+ // Got the files in the dataset
+ StorageContent srcFiles = new StorageContent(files.size());
+ for(var file : files) {
+ srcFiles.elements.add(new StorageElement(file, this.baseUrl));
+ }
+
+ srcFiles.count = srcFiles.elements.size();
+
+ // Success
+ return Uni.createFrom().item(srcFiles);
+ })
+ .onFailure().invoke(e -> {
+ LOG.errorf("Failed to parse ESRF DOI %s", doi);
+ });
+
+ return result;
+ }
+
+}
diff --git a/src/main/java/parser/esrf/model/EsrfCredentials.java b/src/main/java/parser/esrf/model/EsrfCredentials.java
new file mode 100644
index 0000000..0175d33
--- /dev/null
+++ b/src/main/java/parser/esrf/model/EsrfCredentials.java
@@ -0,0 +1,25 @@
+package parser.esrf.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+
+/**
+ * Credentials for ESRF
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class EsrfCredentials {
+
+ public String username;
+ public String password;
+ public String plugin = "db";
+
+ /***
+ * Create from credentials
+ * @param username ESRF username
+ * @param password Password for the user
+ */
+ public EsrfCredentials(String username, String password) {
+ this.username = username;
+ this.password = password;
+ }
+}
diff --git a/src/main/java/parser/esrf/model/EsrfDataFile.java b/src/main/java/parser/esrf/model/EsrfDataFile.java
new file mode 100644
index 0000000..8aa663a
--- /dev/null
+++ b/src/main/java/parser/esrf/model/EsrfDataFile.java
@@ -0,0 +1,32 @@
+package parser.esrf.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import java.util.Date;
+
+
+/**
+ * ESRF file
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class EsrfDataFile {
+
+ public Info Datafile;
+
+ /***
+ * Constructor
+ */
+ public EsrfDataFile() {}
+
+ /***
+ * The details of the ESRF file
+ */
+ public class Info {
+ public String id;
+ public String name;
+ public Date createTime;
+ public Date modTime;
+ public long fileSize;
+ public String location;
+ }
+}
diff --git a/src/main/java/parser/esrf/model/EsrfDataSet.java b/src/main/java/parser/esrf/model/EsrfDataSet.java
new file mode 100644
index 0000000..1efbf76
--- /dev/null
+++ b/src/main/java/parser/esrf/model/EsrfDataSet.java
@@ -0,0 +1,24 @@
+package parser.esrf.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import java.util.Date;
+
+
+/**
+ * ESRF dataset
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class EsrfDataSet {
+
+ public String id;
+ public String name;
+ public Date startDate;
+ public Date endDate;
+ public String location;
+
+ /***
+ * Constructor
+ */
+ public EsrfDataSet() {}
+}
diff --git a/src/main/java/parser/esrf/model/EsrfSession.java b/src/main/java/parser/esrf/model/EsrfSession.java
new file mode 100644
index 0000000..17ba06d
--- /dev/null
+++ b/src/main/java/parser/esrf/model/EsrfSession.java
@@ -0,0 +1,23 @@
+package parser.esrf.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+
+/**
+ * ESRF session
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class EsrfSession {
+
+ public String sessionId;
+ public double lifeTimeMinutes;
+ public String name;
+ public boolean isAdministrator;
+ public boolean isInstrumentScientist;
+ public boolean isMinter;
+
+ /***
+ * Constructor
+ */
+ public EsrfSession() {}
+}
diff --git a/src/main/java/parser/generic/SignpostParser.java b/src/main/java/parser/generic/SignpostParser.java
index f02ed52..e291fde 100644
--- a/src/main/java/parser/generic/SignpostParser.java
+++ b/src/main/java/parser/generic/SignpostParser.java
@@ -52,7 +52,6 @@ public class SignpostParser implements ParserService {
* @return true on success
*/
public boolean init(ParserConfig config, PortConfig port) {
-
this.name = config.name();
this.timeout = config.timeout();
diff --git a/src/main/java/parser/zenodo/ZenodoException.java b/src/main/java/parser/zenodo/ZenodoException.java
index dfd45eb..9ecaff5 100644
--- a/src/main/java/parser/zenodo/ZenodoException.java
+++ b/src/main/java/parser/zenodo/ZenodoException.java
@@ -15,10 +15,19 @@ public ZenodoException() {
super();
}
+ /***
+ * Construct from a response
+ * @param resp Response object
+ * @param body Response body
+ */
public ZenodoException(Response resp, String body) {
super(resp);
this.responseBody = body;
}
+ /***
+ * Get the response body
+ * @return Body of the response
+ */
String responseBody() { return responseBody; }
}
diff --git a/src/main/java/parser/zenodo/ZenodoParser.java b/src/main/java/parser/zenodo/ZenodoParser.java
index 22f4882..c142068 100644
--- a/src/main/java/parser/zenodo/ZenodoParser.java
+++ b/src/main/java/parser/zenodo/ZenodoParser.java
@@ -41,14 +41,12 @@ public class ZenodoParser implements ParserService {
public ZenodoParser(String id) { this.id = id; }
/***
- * Initialize the REST client for B2Share.
- * The hostname of the B2Share server should be already determined by a previous call to canParseDOI().
+ * Initialize the REST client for Zenodo.
* @param config Configuration of the parser, from the config file.
* @param port The port on which the application runs, from the config file.
* @return true on success
*/
public boolean init(ParserConfig config, PortConfig port) {
-
this.name = config.name();
this.timeout = config.timeout();
@@ -108,7 +106,6 @@ public boolean init(ParserConfig config, PortConfig port) {
* @return Return true if the parser service can parse this DOI.
*/
public Uni> canParseDOI(String auth, String doi, ParserHelper helper) {
- // Validate DOI without actually fetching the URL
boolean isValid = null != doi && !doi.isBlank();
if(!isValid)
return Uni.createFrom().failure(new TransferServiceException("doiInvalid"));
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 915dda8..53b7ae4 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -6,6 +6,10 @@ eosc:
class: parser.zenodo.ZenodoParser
url: https://zenodo.org
timeout: 5000
+ esrf:
+ name: European Synchrotron Radiation Facility
+ class: parser.esrf.EsrfParser
+ url: https://icatplus.esrf.fr
b2share:
name: B2Share
class: parser.b2share.B2ShareParser
@@ -86,7 +90,7 @@ quarkus:
urls-primary-name: default
smallrye-openapi:
path: /openapi
- info-version: 1.1.40
+ info-version: 1.1.41
jackson:
fail-on-unknown-properties: false
http: