From 24cd5762b2207438c8706b2d7065b92e534928d3 Mon Sep 17 00:00:00 2001 From: Patrick Austin Date: Wed, 4 Dec 2024 14:04:32 +0000 Subject: [PATCH] Implement GET DownloadStatus endpoint #52 --- .../topcat/repository/DownloadRepository.java | 35 ++++++++++++ .../topcat/web/rest/UserResource.java | 30 ++++++++++ .../icatproject/topcat/UserResourceTest.java | 57 +++++++++++++++++++ 3 files changed, 122 insertions(+) diff --git a/src/main/java/org/icatproject/topcat/repository/DownloadRepository.java b/src/main/java/org/icatproject/topcat/repository/DownloadRepository.java index 1ee2cd57..201ff29f 100644 --- a/src/main/java/org/icatproject/topcat/repository/DownloadRepository.java +++ b/src/main/java/org/icatproject/topcat/repository/DownloadRepository.java @@ -5,6 +5,7 @@ import java.text.SimpleDateFormat; import java.text.DateFormat; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Locale; @@ -21,7 +22,9 @@ import jakarta.persistence.TypedQuery; import org.icatproject.topcat.domain.Download; +import org.icatproject.topcat.domain.DownloadStatus; import org.icatproject.topcat.exceptions.BadRequestException; +import org.icatproject.topcat.exceptions.NotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,6 +100,38 @@ public List getDownloads(Map params) throws ParseExcep return downloads; } + /** + * Get the statuses from downloadIds. + * + * @param userName The formatted userName corresponding to the sessionId that + * submitted the request + * @param downloadIds List of ids to check + * @return List of DownloadStatus for each downloadId + * @throws NotFoundException If less Downloads are found than ids provided. In + * practice, this either means the Download(s) do not + * exist or they did not belong to the user submitting + * the request. + */ + public List getStatuses(String userName, List downloadIds) throws NotFoundException { + StringBuilder stringBuilder = new StringBuilder(); + Iterator downloadIdIterator = downloadIds.iterator(); + stringBuilder.append(downloadIdIterator.next()); + downloadIdIterator.forEachRemaining(downloadId -> { + stringBuilder.append(","); + stringBuilder.append(downloadId); + }); + String queryString = "SELECT download.status FROM Download download WHERE download.userName = '" + userName; + queryString += "' AND download.id IN (" + stringBuilder.toString() + ")"; + TypedQuery query = em.createQuery(queryString, DownloadStatus.class); + List resultList = query.getResultList(); + + if (resultList.size() < downloadIds.size()) { + throw new NotFoundException("Could not find a Download for each provided id"); + } + + return resultList; + } + public Download getDownload(Long id) { return em.find(Download.class, id); } diff --git a/src/main/java/org/icatproject/topcat/web/rest/UserResource.java b/src/main/java/org/icatproject/topcat/web/rest/UserResource.java index 1ce2602f..a9e484f4 100644 --- a/src/main/java/org/icatproject/topcat/web/rest/UserResource.java +++ b/src/main/java/org/icatproject/topcat/web/rest/UserResource.java @@ -153,6 +153,36 @@ public Response getDownloads(@QueryParam("facilityName") String facilityName, @Q }).build(); } + /** + * Get the statuses of one or more in progress Downloads. + * + * @param facilityName ICAT Facility.name + * @param sessionId ICAT sessionId, only carts belonging to the ICAT user + * this resolves to will be returned. + * @param downloadIds One or more ids for the Download(s) to check + * @return Array of DownloadStatus values + * @throws TopcatException + * @throws MalformedURLException + * @throws ParseException + */ + @GET + @Path("/downloads/status") + @Produces({ MediaType.APPLICATION_JSON }) + public Response getDownloadStatuses(@QueryParam("facilityName") String facilityName, + @QueryParam("sessionId") String sessionId, @QueryParam("downloadIds") List downloadIds) + throws TopcatException, MalformedURLException, ParseException { + + if (downloadIds.size() == 0) { + throw new BadRequestException("At least one downloadId required"); + } + String icatUrl = getIcatUrl(facilityName); + IcatClient icatClient = new IcatClient(icatUrl, sessionId); + String cartUserName = getCartUserName(icatClient.getUserName(), sessionId); + List statuses = downloadRepository.getStatuses(cartUserName, downloadIds); + + return Response.ok().entity(statuses).build(); + } + /** * Sets whether or not a download is deleted associated with a particular * sessionId. diff --git a/src/test/java/org/icatproject/topcat/UserResourceTest.java b/src/test/java/org/icatproject/topcat/UserResourceTest.java index 2ee7f646..38712b40 100644 --- a/src/test/java/org/icatproject/topcat/UserResourceTest.java +++ b/src/test/java/org/icatproject/topcat/UserResourceTest.java @@ -12,6 +12,7 @@ import static org.junit.Assert.*; import org.junit.*; +import org.junit.function.ThrowingRunnable; import org.junit.runner.RunWith; import jakarta.inject.Inject; @@ -21,6 +22,11 @@ import org.icatproject.topcat.httpclient.HttpClient; import org.icatproject.topcat.domain.*; +import org.icatproject.topcat.exceptions.BadRequestException; +import org.icatproject.topcat.exceptions.NotFoundException; +import org.icatproject.topcat.exceptions.TopcatException; + +import java.net.MalformedURLException; import java.net.URLEncoder; import org.icatproject.topcat.repository.CacheRepository; @@ -30,6 +36,7 @@ import org.icatproject.topcat.web.rest.UserResource; import java.sql.*; +import java.text.ParseException; @RunWith(Arquillian.class) public class UserResourceTest { @@ -276,6 +283,56 @@ public void testGetDownloadTypeStatus() throws Exception { } } + @Test + public void testGetDownloadStatusesBadRequest() throws MalformedURLException, TopcatException, ParseException { + ThrowingRunnable runnable = () -> userResource.getDownloadStatuses("LILS", sessionId, new ArrayList<>()); + assertThrows(BadRequestException.class, runnable); + } + + @Test + public void testGetDownloadNotFound() throws MalformedURLException, TopcatException, ParseException { + List downloadIds = new ArrayList<>(); + try { + Download download = new Download(); + download.setFacilityName("LILS"); + download.setUserName("simple/notroot"); + download.setTransport("http"); + download.setFileName("fileName"); + download.setSessionId(sessionId); + download.setStatus(DownloadStatus.COMPLETE); + download = downloadRepository.save(download); + downloadIds.add(download.getId()); + ThrowingRunnable runnable = () -> userResource.getDownloadStatuses("LILS", sessionId, downloadIds); + assertThrows(NotFoundException.class, runnable); + } finally { + downloadIds.forEach(downloadId -> { + downloadRepository.removeDownload(downloadId); + }); + } + } + + @Test + public void testGetDownloadStatuses() throws MalformedURLException, TopcatException, ParseException { + List downloadIds = new ArrayList<>(); + try { + Download download = new Download(); + download.setFacilityName("LILS"); + download.setUserName("simple/root"); + download.setTransport("http"); + download.setFileName("fileName"); + download.setSessionId(sessionId); + download.setStatus(DownloadStatus.COMPLETE); + download = downloadRepository.save(download); + downloadIds.add(download.getId()); + Response response = userResource.getDownloadStatuses("LILS", sessionId, downloadIds); + assertEquals(Arrays.asList(DownloadStatus.COMPLETE), response.getEntity()); + } finally { + downloadIds.forEach(downloadId -> { + downloadRepository.removeDownload(downloadId); + }); + } + } + private int getCartSize(Response response) throws Exception { // Trying to write these tests has revealed that UserResource.getSize() is // inconsistent!