Skip to content

Commit 886a602

Browse files
committed
Merge branch 'dev'
2 parents 5790072 + a567bfa commit 886a602

File tree

9 files changed

+41
-19
lines changed

9 files changed

+41
-19
lines changed

docs/export_objects.adoc

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ To include files in folder(s) it is possible to add the following attributes:
2525
"exportLayout": { "subfolder/" : ["fileUUID"] }
2626
```
2727

28+
It is also possible to use an alternative name (alias) for files:
29+
```
30+
"filenameAliases": { "fileUUID" : "myFileAlias" }
31+
```
2832

2933
== Export processing
3034

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>ca.gc.aafc</groupId>
77
<artifactId>object-store.api</artifactId>
8-
<version>1.23</version>
8+
<version>1.24</version>
99
<packaging>jar</packaging>
1010

1111
<name>Object-Store API</name>

src/main/java/ca/gc/aafc/objectstore/api/dto/ObjectExportDto.java

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class ObjectExportDto {
2525
private UUID uuid;
2626

2727
private List<UUID> fileIdentifiers;
28+
private Map<UUID, String> filenameAliases;
2829
private Map<String, List<UUID>> exportLayout;
2930
private String name;
3031

src/main/java/ca/gc/aafc/objectstore/api/file/FileController.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public ResponseEntity<InputStreamResource> downloadObject(
206206

207207
// For the download of an object use the originalFilename provided (if possible)
208208
return download(bucket, metadata.getFilename(),
209-
ObjectFilenameUtils.generateMainObjectFilename(metadata),
209+
ObjectFilenameUtils.generateMainObjectFilename(metadata, null),
210210
false, metadata.getDcFormat(), metadata);
211211
}
212212

@@ -246,7 +246,7 @@ public ResponseEntity<InputStreamResource> downloadDerivative(
246246
.orElseThrow(() -> buildNotFoundException(bucket, Objects.toString(fileId)));
247247

248248
return download(bucket, derivative.getFilename(),
249-
ObjectFilenameUtils.generateDerivativeFilename(derivative), true, derivative.getDcFormat(), derivative);
249+
ObjectFilenameUtils.generateDerivativeFilename(derivative, null), true, derivative.getDcFormat(), derivative);
250250
}
251251

252252
@GetMapping("/file/{bucket}/{fileId}/thumbnail")

src/main/java/ca/gc/aafc/objectstore/api/file/ObjectExportGenerator.java

+12-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
1717
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
1818
import org.apache.commons.io.IOUtils;
19+
import org.apache.commons.lang3.StringUtils;
1920
import org.springframework.scheduling.annotation.Async;
2021
import org.springframework.stereotype.Service;
2122

@@ -40,9 +41,11 @@ public ObjectExportGenerator(FileStorage fileStorage) {
4041

4142
@Async(MainConfiguration.DINA_THREAD_POOL_BEAN_NAME)
4243
public CompletableFuture<UUID> export(UUID exportUUID, List<AbstractObjectStoreMetadata> objectsToExport,
44+
Map<UUID, String> aliases,
4345
Map<String, List<UUID>> exportLayout, Path zipFile) {
4446

4547
Map<UUID, String> layoutByFileIdentifier = invertExportLayout(exportLayout);
48+
Map<UUID, String> filenameAliases = aliases == null ? Map.of() : aliases;
4649
Map<String, AtomicInteger> filenamesIncluded = new HashMap<>();
4750

4851
try (ArchiveOutputStream<ZipArchiveEntry> o = new ZipArchiveOutputStream(zipFile)) {
@@ -53,7 +56,8 @@ public CompletableFuture<UUID> export(UUID exportUUID, List<AbstractObjectStoreM
5356

5457
// Set zipEntry with information from fileStorage
5558
ZipArchiveEntry entry =
56-
new ZipArchiveEntry(generateExportItemFilename(currObj, layoutByFileIdentifier, filenamesIncluded));
59+
new ZipArchiveEntry(generateExportItemFilename(currObj, filenameAliases.get(currObj.getFileIdentifier()),
60+
layoutByFileIdentifier.get(currObj.getFileIdentifier()), filenamesIncluded));
5761
entry.setSize(
5862
fileInfo.orElseThrow(() -> new IllegalStateException("No FileInfo found")).getLength());
5963
o.putArchiveEntry(entry);
@@ -79,25 +83,26 @@ public CompletableFuture<UUID> export(UUID exportUUID, List<AbstractObjectStoreM
7983
* Get a unique (withing the export) filename.
8084
*
8185
* @param obj the data about the file to add
86+
* @param filenameAlias use an alternative name for the filename
87+
* @param folder folder to which the file should be stored under
8288
* @param usedFilenames filenames that are already used with a counter. Will be modified by this function.
8389
* @return
8490
*/
8591
private static String generateExportItemFilename(AbstractObjectStoreMetadata obj,
86-
Map<UUID, String> layoutByFileIdentifier,
92+
String filenameAlias, String folder,
8793
Map<String, AtomicInteger> usedFilenames) {
8894
String filename;
89-
9095
if (obj instanceof ObjectStoreMetadata metadata) {
91-
filename = ObjectFilenameUtils.generateMainObjectFilename(metadata);
96+
filename = ObjectFilenameUtils.generateMainObjectFilename(metadata, filenameAlias);
9297
} else if (obj instanceof Derivative derivative) {
93-
filename = ObjectFilenameUtils.generateDerivativeFilename(derivative);
98+
filename = ObjectFilenameUtils.generateDerivativeFilename(derivative, filenameAlias);
9499
} else {
95100
filename = obj.getFilename();
96101
}
97102

98103
// Do we have an export layout to consider ?
99-
if (layoutByFileIdentifier.containsKey(obj.getFileIdentifier())) {
100-
String folderName = ObjectFilenameUtils.standardizeFolderName(layoutByFileIdentifier.get(obj.getFileIdentifier()));
104+
if (StringUtils.isNotBlank(folder)) {
105+
String folderName = ObjectFilenameUtils.standardizeFolderName(folder);
101106
filename = folderName + filename;
102107
}
103108

src/main/java/ca/gc/aafc/objectstore/api/repository/ObjectExportRepository.java

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public <S extends ObjectExportDto> S create(S s) {
3333
objectExportService.export(ObjectExportService.ExportArgs.builder()
3434
.username(authenticatedUser.getUsername())
3535
.fileIdentifiers(s.getFileIdentifiers())
36+
.filenameAliases(s.getFilenameAliases())
3637
.exportLayout(s.getExportLayout())
3738
.name(s.getName())
3839
.build());

src/main/java/ca/gc/aafc/objectstore/api/service/ObjectExportService.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ public UUID export(ExportArgs exportArgs) {
127127

128128
// then complete the export
129129
CompletableFuture<ExportResult> completableFuture =
130-
objectExportGenerator.export(exportUUID, toExport, exportArgs.exportLayout(), zipFile)
130+
objectExportGenerator.export(exportUUID, toExport, exportArgs.filenameAliases(),
131+
exportArgs.exportLayout(), zipFile)
131132
.thenApply(uuid -> {
132133
String toaKey = toaCtrl.registerObject(filename);
133134
log.info("Generated toaKey {}", () -> toaKey);
@@ -166,11 +167,13 @@ private static void throwIllegalStateFileNotFound(UUID fileIdentifier) throws Il
166167
/**
167168
* @param username the username of the user requesting the export
168169
* @param fileIdentifiers list of files identifier to export
170+
* @param filenameAliases map of fileIdentifier to optional filename alias
169171
* @param exportLayout folder structure of the export (optional)
170172
* @param name optional name of the export (optional)
171173
*/
172174
@Builder
173175
public record ExportArgs(String username, List<UUID> fileIdentifiers,
176+
Map<UUID, String> filenameAliases,
174177
Map<String, List<UUID>> exportLayout, String name) {
175178

176179
}

src/main/java/ca/gc/aafc/objectstore/api/util/ObjectFilenameUtils.java

+14-7
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ public static String standardizeFolderName(String userSubmittedFolderName) {
6969
* Generate a filename (with file extension) for a derivative. Since Derivatives don't have a name we are trying to use the name
7070
* of the derivedFrom and add the derivative type as suffix. We will use a fallback on derivative's uuid.
7171
* @param derivative non null
72+
* @param filenameAlias optional, an alias to use instead of the originalFilename of the derivedFrom
7273
* @return a filename like myUploadedImage_thumbnail.jpg
7374
*/
74-
public static String generateDerivativeFilename(Derivative derivative) {
75+
public static String generateDerivativeFilename(Derivative derivative, String filenameAlias) {
7576
Objects.requireNonNull(derivative);
7677

7778
ObjectStoreMetadata derivedFrom = derivative.getAcDerivedFrom();
@@ -80,8 +81,12 @@ public static String generateDerivativeFilename(Derivative derivative) {
8081
String derivativeSuffix =
8182
derivative.getDerivativeType() != null ? derivative.getDerivativeType().getSuffix() :
8283
"derivative";
84+
85+
String filename = StringUtils.isBlank(filenameAlias) ? derivedFrom.getOriginalFilename() :
86+
standardizeFilename(filenameAlias);
87+
8388
// generate a name from the originalFilename + the generated suffix + the derivative file extension (since it might be different from the original)
84-
return FilenameUtils.getBaseName(derivedFrom.getOriginalFilename()) + "_" + derivativeSuffix + derivative.getFileExtension();
89+
return FilenameUtils.getBaseName(filename) + "_" + derivativeSuffix + derivative.getFileExtension();
8590
}
8691
//fallback, use the internal name
8792
return derivative.getFilename();
@@ -91,19 +96,21 @@ public static String generateDerivativeFilename(Derivative derivative) {
9196
* Make sure a valid filename is generated for the download.
9297
*
9398
* @param mainObject
94-
* @return
99+
* @param filenameAlias optional, an alias to use instead of the originalFilename
100+
* @return generated filename including file extension
95101
*/
96-
public static String generateMainObjectFilename(ObjectStoreMetadata mainObject) {
102+
public static String generateMainObjectFilename(ObjectStoreMetadata mainObject, String filenameAlias) {
97103
Objects.requireNonNull(mainObject);
98104

99-
String originalFilename = mainObject.getOriginalFilename();
105+
String filename = StringUtils.isBlank(filenameAlias) ? mainObject.getOriginalFilename() :
106+
standardizeFilename(filenameAlias);
100107

101108
// if there is no original file name of the filename is just an extension
102-
if (StringUtils.isEmpty(originalFilename) || StringUtils.isEmpty(FilenameUtils.getBaseName(originalFilename))) {
109+
if (StringUtils.isEmpty(filename) || StringUtils.isEmpty(FilenameUtils.getBaseName(filename))) {
103110
return mainObject.getFilename();
104111
}
105112
// use the internal extension since we are also returning the internal media type
106-
return FilenameUtils.getBaseName(originalFilename) + mainObject.getFileExtension();
113+
return FilenameUtils.getBaseName(filename) + mainObject.getFileExtension();
107114
}
108115

109116
/**

src/test/java/ca/gc/aafc/objectstore/api/service/ObjectExportServiceIT.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public void exportObjects_onExport_ZipContentValid()
9595
.username("testuser")
9696
.fileIdentifiers(List.of(osm.getFileIdentifier(), thumbnail.get().getFileIdentifier()))
9797
.exportLayout(Map.of("thumb/", List.of(thumbnail.get().getFileIdentifier())))
98+
.filenameAliases(Map.of(osm.getFileIdentifier(), "testFileAlias"))
9899
.username("testname").build());
99100

100101
// 5 - Wait for completion
@@ -121,7 +122,7 @@ public void exportObjects_onExport_ZipContentValid()
121122
}
122123

123124
assertEquals(2, filenamesInZip.size());
124-
assertTrue(filenamesInZip.contains("testfile.png"));
125+
assertTrue(filenamesInZip.contains("testFileAlias.png"));
125126
assertTrue(filenamesInZip.contains("thumb/testfile_thumbnail.jpg"));
126127
}
127128

0 commit comments

Comments
 (0)