Skip to content

Commit

Permalink
feat: use sims name when exporting (#796)
Browse files Browse the repository at this point in the history
* feat: use sims name when exporting

* fix: solve unit test

* fix: solve sonar issue

* fix: remove ascii char in the zip archive

* fix: remove unused code

* feat: remove filename generation from the HttpUtils class

* feat: review the entire strategy for filename

* feat: add unit test

* feat: add unit test

* feat: finish filename process

* review
  • Loading branch information
EmmanuelDemey authored Nov 28, 2024
1 parent 58d5ab7 commit d024ec8
Show file tree
Hide file tree
Showing 16 changed files with 249 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public void exportZipCollection(String ids, String acceptHeader, HttpServletResp

private String getFileNameForExport(CollectionForExport collection, ConceptsCollectionsResources.Language lg){
String label = (lg == ConceptsCollectionsResources.Language.lg2 && collection.getPrefLabelLg2() != null) ? collection.getPrefLabelLg2() : collection.getPrefLabelLg1();
return FilesUtils.reduceFileNameSize(CaseUtils.toCamelCase(label, false) + "-" + collection.getId(), maxLength);
return FilesUtils.generateFinalFileNameWithoutExtension(collection.getId() + "-" + label, maxLength);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import fr.insee.rmes.utils.XMLUtils;
import fr.insee.rmes.webservice.ConceptsCollectionsResources;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.text.CaseUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
Expand All @@ -42,7 +41,6 @@ public class ConceptsImpl extends RdfService implements ConceptsService {

private static final String THE_CONCEPT = "The concept ";


static final Logger logger = LoggerFactory.getLogger(ConceptsImpl.class);

private final ConceptsUtils conceptsUtils;
Expand Down Expand Up @@ -264,13 +262,13 @@ public void exportZipConcept(String ids, String acceptHeader, HttpServletRespons

public String getFileNameForExport(CollectionForExport collection, ConceptsCollectionsResources.Language lg){
if (lg == ConceptsCollectionsResources.Language.lg2){
return FilesUtils.reduceFileNameSize(CaseUtils.toCamelCase(collection.getPrefLabelLg2(), false) + "-" + collection.getId(), this.maxLength);
return FilesUtils.generateFinalFileNameWithoutExtension(collection.getId() + "-" + collection.getPrefLabelLg2(), this.maxLength);
}
return FilesUtils.reduceFileNameSize(CaseUtils.toCamelCase(collection.getPrefLabelLg1(), false) + "-" + collection.getId(), this.maxLength);
return FilesUtils.generateFinalFileNameWithoutExtension(collection.getId() + "-" + collection.getPrefLabelLg1(), this.maxLength);
}

private String getFileNameForExport(ConceptForExport concept) {
return FilesUtils.reduceFileNameSize(CaseUtils.toCamelCase(concept.getPrefLabelLg1(), false) + "-" + concept.getId(), maxLength);
return FilesUtils.generateFinalFileNameWithoutExtension(concept.getId() + "-" + concept.getPrefLabelLg1(), maxLength);
}

private MembersLg convertConceptIntoMembers(ConceptForExport concept){
Expand Down Expand Up @@ -349,7 +347,7 @@ public ResponseEntity<?> getCollectionExport(String id, String acceptHeader) thr
return ResponseEntity.status(e.getStatus()).contentType(MediaType.TEXT_PLAIN).body(e.getDetails());
}
Map<String, String> xmlContent = convertCollectionInXml(collection);
String fileName = FilesUtils.reduceFileNameSize(CaseUtils.toCamelCase(collection.getPrefLabelLg1(), false) + "-" + collection.getId(), maxLength);
String fileName = FilesUtils.generateFinalFileNameWithoutExtension(collection.getId() + "-" + collection.getPrefLabelLg1(), maxLength);
return collectionExport.exportAsResponse(fileName,xmlContent,true,true,true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import fr.insee.rmes.utils.FilesUtils;
import fr.insee.rmes.utils.JSONUtils;
import fr.insee.rmes.webservice.ConceptsCollectionsResources;
import org.apache.commons.text.CaseUtils;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.impl.LinkedHashModel;
Expand All @@ -44,9 +43,7 @@
public class ConceptsUtils extends RdfService {

private static final Logger logger = LoggerFactory.getLogger(ConceptsUtils.class);

private final ConceptsPublication conceptsPublication;

private final NoteManager noteManager;
private final int maxLength;

Expand All @@ -62,7 +59,7 @@ public String getConceptExportFileName(ConceptForExport concept) {

private String getAbstractExportFileName(String id, String labelLg1, String labelLg2, ConceptsCollectionsResources.Language lg){
var initialFileName = getInitialFileName(labelLg1, labelLg2, lg);
return FilesUtils.reduceFileNameSize(id + "-" + FilesUtils.removeAsciiCharacters(CaseUtils.toCamelCase(initialFileName, false)), maxLength);
return FilesUtils.generateFinalFileNameWithoutExtension(id + "-" + initialFileName, maxLength);
}

private String getInitialFileName(String labelLg1, String labelLg2, ConceptsCollectionsResources.Language lg){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class OperationsDocumentationsImpl extends RdfService implements Operati
@Value("classpath:bauhaus-sims.json")
org.springframework.core.io.Resource simsDefaultValue;

@Value("${fr.insee.rmes.bauhaus.filenames.maxlength}") int maxLength;

@Autowired
DocumentationsUtils documentationsUtils;

Expand Down Expand Up @@ -147,13 +149,13 @@ public ResponseEntity<Resource> exportMetadataReport(String id, boolean includeE
ErrorCodes.SIMS_EXPORT_WITHOUT_LANGUAGE,
"at least one language must be selected for export",
"in export of sims: " + id);
return documentationsExport.exportMetadataReport(id,includeEmptyMas, lg1, lg2, document, Constants.GOAL_RMES);
return documentationsExport.exportMetadataReport(id,includeEmptyMas, lg1, lg2, document, Constants.GOAL_RMES, maxLength);

}

@Override
public ResponseEntity<?> exportMetadataReportForLabel(String id) throws RmesException {
return documentationsExport.exportMetadataReport(id,true, true, false, false, Constants.GOAL_COMITE_LABEL);
return documentationsExport.exportMetadataReport(id,true, true, false, false, Constants.GOAL_COMITE_LABEL, maxLength);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,26 +89,28 @@ public DocumentationExport(@Value("${fr.insee.rmes.bauhaus.filenames.maxlength}"
* the export will be a .ODT file.
*/
public ResponseEntity<Resource> exportAsResponse(String id, Map<String, String> xmlContent, String targetType, boolean includeEmptyFields, boolean lg1,
boolean lg2, boolean documents, String goal) throws RmesException {
boolean lg2, boolean documents, String goal, int maxLength) throws RmesException {

PatternAndZip patternAndZip = PatternAndZip.of(goal);
String parametersXML = XsltUtils.buildParams(lg1, lg2, includeEmptyFields, targetType);
xmlContent.put(Constants.PARAMETERS_FILE, parametersXML);

Exporter exporter;
JSONObject sims = this.documentationsUtils.getDocumentationByIdSims(id);

if (documents) {
JSONObject sims = this.documentationsUtils.getDocumentationByIdSims(id);
exporter = (xml, xsl, xmlPattern, zip, documentation) -> exportAsZip(sims, xml, xsl, xmlPattern, zip, documentation );
exporter = (xml, xsl, xmlPattern, zip, documentation) -> exportAsZip(sims, xml, xsl, xmlPattern, zip, documentation, maxLength);
} else{
exporter = (xml, xsl, xmlPattern, zip, documentation) -> exportUtils.exportAsODT(id, xml, xsl, xmlPattern, zip, documentation );
String fileName = FilesUtils.generateFinalFileNameWithoutExtension(sims.getString(Constants.LABEL_LG1), maxLength);
exporter = (xml, xsl, xmlPattern, zip, documentation) -> exportUtils.exportAsODT(fileName, xml, xsl, xmlPattern, zip, documentation );
}
return export(exporter, xmlContent, patternAndZip);
}

public ResponseEntity<Resource> exportAsZip(JSONObject sims, Map<String, String> xmlContent, String xslFile, String xmlPattern, String zip, String objectType) throws RmesException {
public ResponseEntity<Resource> exportAsZip(JSONObject sims, Map<String, String> xmlContent, String xslFile, String xmlPattern, String zip, String objectType, int maxLength) throws RmesException {
String simsId = sims.getString("id");
logger.debug("Begin to download the SIMS {} with its documents", simsId);
String fileName = sims.getString("labelLg1");
String fileName = FilesUtils.generateFinalFileNameWithoutExtension(sims.getString(Constants.LABEL_LG1), maxLength);

try {

Expand Down Expand Up @@ -139,7 +141,7 @@ public ResponseEntity<Resource> exportAsZip(JSONObject sims, Map<String, String>
FilesUtils.zipDirectory(simsDirectory.toFile());

logger.debug("Zip created for the SIMS {}", simsId);
HttpHeaders responseHeaders = HttpUtils.generateHttpHeaders(sims.getString("labelLg1"), FilesUtils.ZIP_EXTENSION, this.maxLength);
HttpHeaders responseHeaders = HttpUtils.generateHttpHeaders(fileName, FilesUtils.ZIP_EXTENSION);
responseHeaders.set("X-Missing-Documents", String.join(",", missingDocuments));
Resource resource = new UrlResource(Paths.get(simsDirectory.toString(), simsDirectory.getFileName() + FilesUtils.ZIP_EXTENSION).toUri());
return ResponseEntity.ok()
Expand Down Expand Up @@ -169,7 +171,7 @@ private Set<String> exportRubricsDocuments(JSONObject sims, Path directory) thro
if(!Files.exists(documentPath)){
missingDocuments.add(document.getString("id"));
} else {
String documentFileName = FilesUtils.reduceFileNameSize(UriUtils.getLastPartFromUri(url), maxLength);
String documentFileName = FilesUtils.generateFinalFileNameWithExtension(UriUtils.getLastPartFromUri(url), maxLength);
try (InputStream inputStream = Files.newInputStream(documentPath)){
Path documentDirectory = Path.of(directory.toString(), "documents");
if (!Files.exists(documentDirectory)) {
Expand Down Expand Up @@ -203,12 +205,12 @@ public ResponseEntity<Object> exportXmlFiles(Map<String, String> xmlContent, Str
}


public ResponseEntity<Resource> exportMetadataReport(String id, Boolean includeEmptyMas, Boolean lg1, Boolean lg2, Boolean document, String goal) throws RmesException {
public ResponseEntity<Resource> exportMetadataReport(String id, Boolean includeEmptyMas, Boolean lg1, Boolean lg2, Boolean document, String goal, int maxLength) throws RmesException {
Map<String,String> xmlContent = new HashMap<>();
String targetType = getXmlContent(id, xmlContent);
String msdXML = buildShellSims();
xmlContent.put("msdFile", msdXML);
return exportAsResponse(id, xmlContent,targetType,includeEmptyMas,lg1,lg2, document, goal);
return exportAsResponse(id, xmlContent,targetType,includeEmptyMas,lg1,lg2, document, goal, maxLength);
}


Expand Down
6 changes: 3 additions & 3 deletions src/main/java/fr/insee/rmes/utils/ExportUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public ResponseEntity<Resource> exportAsODS(String fileName, Map<String, String>

private ResponseEntity<Resource> exportAsFileByExtension(String fileName, Map<String, String> xmlContent, String xslFile, String xmlPattern, String zip, String objectType, String extension) throws RmesException {
logger.debug("Begin To export {} as Response", objectType);
fileName = fileName.replace(extension, "");
fileName = FilesUtils.generateFinalFileNameWithoutExtension(fileName.replace(extension, ""), maxLength);

InputStream input = exportAsInputStream(fileName, xmlContent, xslFile, xmlPattern, zip, objectType, extension);
if (input == null)
Expand All @@ -67,7 +67,7 @@ private ResponseEntity<Resource> exportAsFileByExtension(String fileName, Map<St
}
logger.debug("End To export {} as Response", objectType);

HttpHeaders responseHeaders = HttpUtils.generateHttpHeaders(fileName, extension, this.maxLength);
HttpHeaders responseHeaders = HttpUtils.generateHttpHeaders(fileName, extension);

return ResponseEntity.ok()
.headers(responseHeaders)
Expand Down Expand Up @@ -151,7 +151,7 @@ public ResponseEntity<Object> exportFilesAsResponse(Map<String, String> xmlConte

logger.debug("End To export temp files as Response");

HttpHeaders responseHeaders = HttpUtils.generateHttpHeaders("xmlFiles", FilesUtils.ZIP_EXTENSION, this.maxLength);
HttpHeaders responseHeaders = HttpUtils.generateHttpHeaders("xmlFiles", FilesUtils.ZIP_EXTENSION);
Resource resource = new UrlResource(Paths.get(tempDir.toString(), tempDir.getFileName() + FilesUtils.ZIP_EXTENSION).toUri());
return ResponseEntity.ok()
.headers(responseHeaders)
Expand Down
58 changes: 28 additions & 30 deletions src/main/java/fr/insee/rmes/utils/FilesUtils.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package fr.insee.rmes.utils;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.text.CaseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.zeroturnaround.zip.FileSource;
import org.zeroturnaround.zip.ZipEntrySource;
import org.zeroturnaround.zip.ZipUtil;

import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.Normalizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
Expand Down Expand Up @@ -50,30 +53,32 @@ public static String getExtension(String acceptHeader) {
}
}

public static String reduceFileNameSize(String fileName, int maxLength) {
return fileName.substring(0, Math.min(fileName.length(), maxLength));
public static String generateFinalFileNameWithExtension(String fileName, int maxLength){
var basename = FilenameUtils.getBaseName(fileName);
var extension = FilenameUtils.getExtension(fileName);
return generateFinalBaseName(basename, maxLength) + "." + extension;
}

public static File streamToFile(InputStream in, String fileName, String fileExtension) throws IOException {
final File tempFile = File.createTempFile(fileName, fileExtension);
tempFile.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(tempFile)) {
IOUtils.copy(in, out);
}
return tempFile;
public static String generateFinalFileNameWithoutExtension(String fileName, int maxLength){
return generateFinalBaseName(fileName, maxLength);
}

public static String cleanFileNameAndAddExtension(String fileName, String extension) {
fileName = fileName.toLowerCase().trim();
fileName = StringUtils.normalizeSpace(fileName);
fileName = fileName.replace(" ", "-");
fileName = Normalizer.normalize(fileName, Normalizer.Form.NFD).replace("[^\\p{ASCII}]", "");
if (extension.startsWith(".")) {
fileName += extension;
} else {
fileName += "." + extension;
}
return fileName;
private static String generateFinalBaseName(String baseName, int maxLength){
return reduceFileNameSize(CaseUtils.toCamelCase(removeAsciiCharacters(baseName), false), maxLength);
}

private static String reduceFileNameSize(String fileName, int maxLength) {
return fileName.substring(0, Math.min(fileName.length(), maxLength));
}

private static String removeAsciiCharacters(String fileName) {
return Normalizer.normalize(fileName, Normalizer.Form.NFD)
.replace("œ", "oe")
.replace("Œ", "OE")
.replaceAll("[-_]", " ")
.replaceAll("\\p{M}+", " ")
.replaceAll("\\p{Punct}", "")
.replace(":", "");
}

public static void addFileToZipFolder(File fileToAdd, File zipArchive) {
Expand All @@ -99,13 +104,6 @@ public static void zipDirectory(File directoryToZip) throws IOException {
}

}
public static String removeAsciiCharacters(String fileName) {
return Normalizer.normalize(fileName, Normalizer.Form.NFD)
.replaceAll("œ", "oe")
.replaceAll("Œ", "OE")
.replaceAll("\\p{M}+", "")
.replaceAll("\\p{Punct}", "");
}

private static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
if (fileToZip.isHidden() || fileName.endsWith(".zip")) {
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/fr/insee/rmes/utils/HttpUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ public final class HttpUtils {
private HttpUtils() {
}

public static HttpHeaders generateHttpHeaders(String fileName, String extension, int maxLength) {
public static HttpHeaders generateHttpHeaders(String fileName, String extension) {
MediaType contentType = FilesUtils.getMediaTypeFromExtension(extension);

ContentDisposition content = ContentDisposition.builder(HttpUtils.ATTACHMENT).filename(
FilesUtils.reduceFileNameSize(
FilesUtils.removeAsciiCharacters(fileName), maxLength) + extension
).build();
fileName + extension)
.build();

List<String> allowHeaders = List.of(CONTENT_DISPOSITION,
"X-Missing-Documents",
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/fr/insee/rmes/utils/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ private StringUtils() {
throw new IllegalStateException("Utility class");
}

public static boolean stringContainsItemFromList(String string, String[] list) {
return Arrays.stream(list).anyMatch(string::contains);
}

public static List<String> stringToList(String value) {
List<String> val = new ArrayList<>();
val.add(value);
Expand Down
Loading

0 comments on commit d024ec8

Please sign in to comment.