From d19e7291ea9dc9647805adf7b4e3a177eea5c9a0 Mon Sep 17 00:00:00 2001 From: Dmitry Netrebenko Date: Mon, 20 Oct 2025 12:22:33 +0300 Subject: [PATCH] feat: add post method for files zip into files api --- .../com/smartling/api/files/v2/FilesApi.java | 19 ++++- .../DownloadMultipleFilesTranslationsPTO.java | 25 +++++++ .../api/files/v2/pto/FileFilter.java | 13 ++++ .../api/files/v2/pto/FileLocalePTO.java | 20 ++++++ .../api/files/v2/FilesApiIntTest.java | 69 ++++++++++++++++++- 5 files changed, 141 insertions(+), 5 deletions(-) create mode 100644 smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/DownloadMultipleFilesTranslationsPTO.java create mode 100644 smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileFilter.java create mode 100644 smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileLocalePTO.java diff --git a/smartling-files-api/src/main/java/com/smartling/api/files/v2/FilesApi.java b/smartling-files-api/src/main/java/com/smartling/api/files/v2/FilesApi.java index 9f4c9c97..af5143ad 100644 --- a/smartling-files-api/src/main/java/com/smartling/api/files/v2/FilesApi.java +++ b/smartling-files-api/src/main/java/com/smartling/api/files/v2/FilesApi.java @@ -2,6 +2,7 @@ import com.smartling.api.files.v2.pto.DeleteFilePTO; import com.smartling.api.files.v2.pto.DownloadAllFileTranslationsPTO; +import com.smartling.api.files.v2.pto.DownloadMultipleFilesTranslationsPTO; import com.smartling.api.files.v2.pto.DownloadMultipleTranslationsPTO; import com.smartling.api.files.v2.pto.DownloadTranslationPTO; import com.smartling.api.files.v2.pto.ExportTranslationsPTO; @@ -19,10 +20,10 @@ import com.smartling.api.files.v2.pto.RenameFilePto; import com.smartling.api.files.v2.pto.UploadFilePTO; import com.smartling.api.files.v2.pto.UploadFileResponse; +import com.smartling.api.files.v2.resteasy.ext.TranslatedFileMultipart; import com.smartling.api.v2.client.exception.server.DetailedErrorMessage; import com.smartling.api.v2.response.EmptyData; import com.smartling.api.v2.response.ListResponse; -import com.smartling.api.files.v2.resteasy.ext.TranslatedFileMultipart; import org.jboss.resteasy.annotations.providers.multipart.MultipartForm; import javax.ws.rs.BeanParam; @@ -33,7 +34,6 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; - import java.io.InputStream; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; @@ -79,11 +79,26 @@ public interface FilesApi extends AutoCloseable @Produces(WILDCARD) InputStream downloadAllFileTranslations(@PathParam("projectId") String projectId, @BeanParam DownloadAllFileTranslationsPTO downloadAllFileTranslationsPTO); + /** + * @deprecated use downloadMultipleFileTranslations with POST method + */ + @Deprecated @GET @Path("/files-api/v2/projects/{projectId}/files/zip") @Produces(WILDCARD) InputStream downloadMultipleFileTranslations(@PathParam("projectId") String projectId, @BeanParam DownloadMultipleTranslationsPTO downloadMultipleTranslationsPTO); + /** + * Download multiple translated files as zip archive + * + * @return {@link InputStream} for zip archive with translated files, if files found for the given file filter; + * null, if no files found for the given file filter. + */ + @POST + @Path("/files-api/v2/projects/{projectId}/files/zip") + @Produces(WILDCARD) + InputStream downloadMultipleFileTranslations(@PathParam("projectId") String projectId, DownloadMultipleFilesTranslationsPTO downloadMultipleTranslationsPTO); + @GET @Path("/files-api/v2/projects/{projectId}/files/list") ListResponse getFilesList(@PathParam("projectId") String projectId, @BeanParam GetFilesListPTO getFilesListPTO); diff --git a/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/DownloadMultipleFilesTranslationsPTO.java b/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/DownloadMultipleFilesTranslationsPTO.java new file mode 100644 index 00000000..59592dea --- /dev/null +++ b/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/DownloadMultipleFilesTranslationsPTO.java @@ -0,0 +1,25 @@ +package com.smartling.api.files.v2.pto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Singular; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class DownloadMultipleFilesTranslationsPTO +{ + @Singular("file") + private List files; + private RetrievalType retrievalType; + private Boolean includeOriginalStrings; + private FileNameMode fileNameMode; + private LocaleMode localeMode; + private String zipFileName; + private FileFilter fileFilter; +} diff --git a/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileFilter.java b/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileFilter.java new file mode 100644 index 00000000..18b6afc0 --- /dev/null +++ b/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileFilter.java @@ -0,0 +1,13 @@ +package com.smartling.api.files.v2.pto; + +public enum FileFilter +{ + /** + * All requested files will be included in the response + */ + ALL_FILES, + /** + * Only fully published files will be included in the response. + */ + PUBLISHED_FILES_ONLY +} diff --git a/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileLocalePTO.java b/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileLocalePTO.java new file mode 100644 index 00000000..701a769e --- /dev/null +++ b/smartling-files-api/src/main/java/com/smartling/api/files/v2/pto/FileLocalePTO.java @@ -0,0 +1,20 @@ +package com.smartling.api.files.v2.pto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Singular; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class FileLocalePTO +{ + private String fileUri; + @Singular("localeId") + private List localeIds; +} diff --git a/smartling-files-api/src/test/java/com/smartling/api/files/v2/FilesApiIntTest.java b/smartling-files-api/src/test/java/com/smartling/api/files/v2/FilesApiIntTest.java index 8ddd9e81..20cac250 100644 --- a/smartling-files-api/src/test/java/com/smartling/api/files/v2/FilesApiIntTest.java +++ b/smartling-files-api/src/test/java/com/smartling/api/files/v2/FilesApiIntTest.java @@ -1,10 +1,15 @@ package com.smartling.api.files.v2; import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.smartling.api.files.v2.pto.DownloadMultipleFilesTranslationsPTO; import com.smartling.api.files.v2.pto.DownloadTranslationPTO; +import com.smartling.api.files.v2.pto.FileFilter; import com.smartling.api.files.v2.pto.FileLocaleLastModifiedPTO; +import com.smartling.api.files.v2.pto.FileLocalePTO; import com.smartling.api.files.v2.pto.FileLocaleStatusResponse; +import com.smartling.api.files.v2.pto.FileNameMode; import com.smartling.api.files.v2.pto.GetFileLastModifiedPTO; +import com.smartling.api.files.v2.pto.LocaleMode; import com.smartling.api.files.v2.pto.UploadFilePTO; import com.smartling.api.files.v2.pto.UploadFileResponse; import com.smartling.api.files.v2.resteasy.ext.TranslatedFileMultipart; @@ -19,7 +24,6 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.net.URL; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -27,6 +31,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aMultipart; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.post; @@ -34,10 +39,12 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; -import static com.smartling.api.v2.tests.wiremock.SmartlingWireMock.success; import static com.smartling.api.files.v2.pto.FileType.JSON; import static com.smartling.api.files.v2.pto.RetrievalType.PUBLISHED; +import static com.smartling.api.v2.tests.wiremock.SmartlingWireMock.postJson; +import static com.smartling.api.v2.tests.wiremock.SmartlingWireMock.success; import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; public class FilesApiIntTest @@ -153,7 +160,7 @@ public void shouldUploadFile() throws Exception .fileUri(FILE_URI) .file(new ByteArrayInputStream(rawBody.getBytes())) .directives(directives) - .localeIdsToAuthorize(Arrays.asList("de-DE", "fr")) + .localeIdsToAuthorize(asList("de-DE", "fr")) .build()); assertEquals(uploadFileResponse.getFileUri(), FILE_URI); @@ -260,4 +267,60 @@ public void shouldGetFileLocaleStatus() throws Exception .withQueryParam("fileUri", equalTo(FILE_URI)) ); } + + @Test + public void shouldRetrieveMultipleFilesTranslations() throws Exception + { + final String rawResponseBody = UUID.randomUUID().toString(); + + final FileLocalePTO firstFileLocalePTO = FileLocalePTO.builder() + .fileUri(FILE_URI + "1") + .localeIds(asList("de-DE", "fr")) + .build(); + + final FileLocalePTO secondFileLocalePTO = FileLocalePTO.builder() + .fileUri(FILE_URI + "2") + .localeIds(asList("es-ES", "uk-UA", "zh-CN")) + .build(); + + final DownloadMultipleFilesTranslationsPTO requestBody = DownloadMultipleFilesTranslationsPTO.builder() + .files(asList(firstFileLocalePTO, secondFileLocalePTO)) + .retrievalType(PUBLISHED) + .includeOriginalStrings(true) + .fileNameMode(FileNameMode.TRIM_LEADING) + .localeMode(LocaleMode.LOCALE_IN_NAME) + .zipFileName("archive.zip") + .fileFilter(FileFilter.PUBLISHED_FILES_ONLY) + .build(); + + smartlingApi.stubFor(postJson(urlPathMatching("/files-api/v2/projects/.+/files/zip")) + .withRequestBody(equalToJson("{\n" + + " \"files\": [{\n" + + " \"fileUri\": \"" + FILE_URI + "1\",\n" + + " \"localeIds\": [\"de-DE\", \"fr\"]\n" + + " },{\n" + + " \"fileUri\": \"" + FILE_URI + "2\",\n" + + " \"localeIds\": [\"es-ES\", \"uk-UA\", \"zh-CN\"]\n" + + " }],\n" + + " \"retrievalType\": \"PUBLISHED\",\n" + + " \"includeOriginalStrings\": true,\n" + + " \"fileNameMode\": \"TRIM_LEADING\",\n" + + " \"localeMode\": \"LOCALE_IN_NAME\",\n" + + " \"zipFileName\": \"archive.zip\",\n" + + " \"fileFilter\": \"PUBLISHED_FILES_ONLY\"\n" + + "}") + ) + .willReturn(aResponse() + .withHeader("Content-Type", "application/octet-stream") + .withBody(rawResponseBody) + ) + ); + + final InputStream response = filesApi.downloadMultipleFileTranslations( + PROJECT_ID, + requestBody + ); + + assertEquals(IOUtils.toString(response, UTF_8), rawResponseBody); + } }