/* * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template */ package com.megatim.fdxconvert.util; import com.megatim.typefichier.validator.utilities.Constantes; import com.megatim.fdxconvert.pojo.DataToImport; import com.megatim.fdxconvert.pojo.FileToValidateDescription; import com.megatim.fdxconvert.exceptions.AttributeFormatException; import static com.megatim.typefichier.validator.utilities.Utilities.getCharset; import com.megatim.fdxconvert.model.AlphaNumeriqueField; import com.megatim.fdxconvert.model.TruncatedElement; import com.megatim.fdxconvert.model.Validateur; import com.megatim.fdxconvert.pojo.ResultFileParsing; import com.megatim.fdxconvert.service.ConfigurationService; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.text.Normalizer; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import org.apache.commons.text.StringEscapeUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * * @author mela */ public class ImportData { /** * Méthode qui parse le fichier csv et en extrait les données * * @param * @param datIm * @return * @throws java.lang.Exception */ public static List importDataFromCsvFile(DataToImport datIm) throws Exception { // FileReader reader = null; List datas = new ArrayList<>(); List listeToReturn = new ArrayList<>(); if (datIm != null) { try ( FileInputStream fis = new FileInputStream(datIm.getFile()); InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(isr)) { String line = ""; while ((line = reader.readLine()) != null) { String[] row = line.split(datIm.getRowDelimiter()); for (String r : row) { String[] values = new String[datIm.getFields().size()]; String[] columns = r.split(datIm.getColumnDelimiter()); int ss = 0; while (ss < datIm.getFields().size() && ss < columns.length) { values[ss] = columns[ss]; ss++; } datas.add(values); } } } catch (FileNotFoundException ex) { Logger.getLogger(ImportData.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } catch (IOException ex) { Logger.getLogger(ImportData.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } if (!datas.isEmpty()) { //tous les champs du type paramétré Field[] fields = datIm.getType().getDeclaredFields(); // mettre les champs du type paramétré dans une map afin de faciliter leur accès Map fieldsToMap = fieldsToMap(fields); datas.forEach(d -> { try { T obj = datIm.getType().newInstance(); Map map = tabToMap(datIm.getFields(), d); for (Field field : fields) { String fieldName = field.getName(); if (map.containsKey(fieldName) && fieldsToMap.containsKey(fieldName)) { try { Object converted = convertToPrimitive(field, map.get(fieldName)); Method method = new PropertyDescriptor(fieldName, datIm.getType()).getWriteMethod(); method.invoke(obj, converted); } catch (IntrospectionException | IllegalAccessException | InvocationTargetException ex) { Logger.getLogger(ImportData.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } catch (IllegalArgumentException | ClassCastException ex) { throw new AttributeFormatException("Erreur de type sur le champ " + fieldName); } } } listeToReturn.add(obj); } catch (InstantiationException | IllegalAccessException ex) { Logger.getLogger(ImportData.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } }); } } return listeToReturn; } /** * Méthode qui extrait les données d'un fichier csv et les normalise * * @param rawCsvData : objet contenant les informations de validationdonnées * @param validateur : Validateur du type fichier auquel appartient le * fichier à valider * @param outputFile : fichier texte généré en sortie * @param headerPresent : renseigne si le fichier a une ligne d'entête * @param alphaNumeriqueToBeTruncated : liste des champs à tronquer * @throws Exception */ public static void parseCsvFile(FileToValidateDescription rawCsvData, Validateur validateur, File outputFile, boolean headerPresent, Set alphaNumeriqueToBeTruncated) throws Exception { Map mapParams = ParserUtils.getValidateurElements(validateur); AtomicInteger numeroLigne = new AtomicInteger(0); AtomicBoolean columnTruncated = new AtomicBoolean(); int lineNumber = 1; if (rawCsvData != null) { Charset charset = getCharset(rawCsvData.getFile()); AtomicBoolean withHeader = new AtomicBoolean(headerPresent); Path pathOfTruncatedElts = createTruncatedEltsPath(validateur, rawCsvData.getFile()); try ( FileInputStream fis = new FileInputStream(rawCsvData.getFile()); InputStreamReader isr = new InputStreamReader(fis, charset); BufferedReader reader = new BufferedReader(isr)) { try ( BufferedWriter bufferWriter = Files.newBufferedWriter(outputFile.toPath(), charset, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.SYNC); BufferedWriter truncateWriter = Files.newBufferedWriter(pathOfTruncatedElts, StandardCharsets.UTF_8, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.SYNC)) { CSVParser parser = new CSVParser(reader, CSVFormat.DEFAULT.builder() .setSkipHeaderRecord(headerPresent) .setIgnoreSurroundingSpaces(true) .setTrim(true) .setDelimiter(StringEscapeUtils.unescapeJava(rawCsvData.getColumnDelimiter())) .setRecordSeparator(StringEscapeUtils.unescapeJava(rawCsvData.getRowDelimiter())) .build()); for (CSVRecord record : parser) { String[] columnsTableLine = new String[record.size()]; AtomicInteger i = new AtomicInteger(0); if (!withHeader.get()) { record.forEach(column -> { columnsTableLine[i.get()] = column != null ? column.replaceAll(" {2,}", " ").replaceAll("\r", "").replaceAll("\n", "").replaceAll("\t", "").trim() : ""; i.set(i.get() + 1); }); //Nettoyage d'une colonne de chaque ligne ResultFileParsing resultFileParsing = buildFinalColumnsTableLine(outputFile, columnsTableLine, mapParams, alphaNumeriqueToBeTruncated, numeroLigne.incrementAndGet(), truncateWriter); String[] finalColumnsTableLine = resultFileParsing.getFinalColumnsTableLine(); columnTruncated.set(resultFileParsing.isColumnTruncated()); String[] encodedStrings = ParserUtils.encodeStrings(finalColumnsTableLine, charset); ParserUtils.writeToFile(encodedStrings, bufferWriter); lineNumber++; } else { withHeader.set(false); } } } catch (Exception e) { Logger.getLogger(ImportData.class.getName()).log(Level.SEVERE, e.getMessage(), e); } //Si au moins une colonne a été tronqué, alors copier le fichier dont les lignes ont été tronqué dans le répertoire d'archivage if (columnTruncated.get()) { Path originalFilePathInArchiveFolder = createOriginalFileInArchive(validateur, rawCsvData.getFile()); //Copie du fichier dont les colonnes ont été tronqués vers le répertoire archivage if (rawCsvData.getFile().exists()) { Files.copy(rawCsvData.getFile().toPath(), originalFilePathInArchiveFolder); } } else {//Sinon supprimer le fichier des éléments tronqués, car il est vide Files.deleteIfExists(pathOfTruncatedElts); } } } } /** * Méthode qui extrait les données dans un fichier txt en respectant * scrupuleusement la taille de chaque colonne * * @param rawCsvData : objet contenant les informations de validationdonnées * @param validateur : Validateur du type fichier auquel appartient le * fichier à valider * @param outputFile : fichier texte généré en sortie * @param headerPresent : renseigne si le fichier a une ligne d'entête * @throws Exception */ public static void parseFileByFieldLength(FileToValidateDescription rawCsvData, Validateur validateur, File outputFile, boolean headerPresent) throws Exception { System.out.println("----------------------In parseFileByFieldLength------------------"); Map mapParams = ParserUtils.getValidateurElements(validateur); //boolean result = true; int nbLine = 0; if (rawCsvData != null) { Charset charset = getCharset(rawCsvData.getFile()); //Lecture des lignes du fichier et chargment dans une liste try ( FileInputStream fis = new FileInputStream(rawCsvData.getFile()); InputStreamReader isr = new InputStreamReader(fis, charset); BufferedReader reader = new BufferedReader(isr)) { try ( //Initialisation du write pour traiter chaque ligne du fichier BufferedWriter bufferWriter = Files.newBufferedWriter(outputFile.toPath(), charset, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.SYNC);) { boolean withHeader = headerPresent; StringBuilder line = new StringBuilder(); int c = 0; boolean carriageReaded = false; //Indique si on a lu un retour chariot char lastCharacter = '\u0000'; while ((c = reader.read()) != -1) { char characterRead = (char) c; if (characterRead == '\r') { if (carriageReaded) { //On a lu le retour chariot deux fois consécutives donc on a pas de séparateur de ligne au sens windows //On ajoute les deux caractère à la chaîne que nous construisons line.append('\r').append(characterRead); carriageReaded = false; //On marque que la lecture d'une nouvelle ligne redémarre } else { // Première lecture du retour chariot carriageReaded = true; // On marque que nous avons lu un retour chariot } } else { if (carriageReaded) { // Le caractère précédemment lu c'est le retour chariot if (characterRead == '\n') { // Si le nouveau caractère lu est un saut de ligne c'est que nous venons de lire une nouvelle ligne //On effectue les traitements propres à la ligne String newLine = line.toString(); nbLine++; if (!withHeader) { parseLineUsingFieldLength(newLine, mapParams, rawCsvData.getColumnDelimiter(), bufferWriter, charset); } else { withHeader = false; } line = new StringBuilder(); //On réinitialise notre constructeur de ligne carriageReaded = false; //On marque que la lecture d'une nouvelle ligne redémarre } else { line.append(' '); //On change le saut de ligne par un espace } } else { if (characterRead == '\n') { if (lastCharacter != '\n') { line.append(' '); } } else { line.append(characterRead); } } } lastCharacter = characterRead; } } //Fermeture du writer } } } /** * Méthode qui parcours un fichier txt caractère par caractère afin d'en * extraire les données et de les normaliser * * @param rawCsvData : objet contenant les informations de validationdonnées * @param validateur : Validateur du type fichier auquel appartient le * fichier à valider * @param outputFile : fichier texte généré en sortie * @param headerPresent : renseigne si le fichier a une ligne d'entête * @param alphaNumeriqueToBeTruncated : liste des champs à tronquer * @throws Exception */ public static void parseFileCharacterByCharacter(FileToValidateDescription rawCsvData, Validateur validateur, File outputFile, boolean headerPresent, Set alphaNumeriqueToBeTruncated) throws Exception { Map mapParams = ParserUtils.getValidateurElements(validateur); AtomicInteger numeroLigne = new AtomicInteger(0); AtomicBoolean columnTruncated = new AtomicBoolean(); if (rawCsvData != null) { Charset charset = getCharset(rawCsvData.getFile()); Path pathOfTruncatedElts = createTruncatedEltsPath(validateur, rawCsvData.getFile()); //Lecture des lignes du fichier et chargement dans une liste try ( FileInputStream fis = new FileInputStream(rawCsvData.getFile()); InputStreamReader isr = new InputStreamReader(fis, charset); BufferedReader reader = new BufferedReader(isr)) { try ( //Initialisation du write pour traiter chaque ligne du fichier BufferedWriter bufferWriter = Files.newBufferedWriter(outputFile.toPath(), charset, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.SYNC); BufferedWriter truncateWriter = Files.newBufferedWriter(pathOfTruncatedElts, StandardCharsets.UTF_8, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.SYNC)) { boolean withHeader = headerPresent; StringBuilder line = new StringBuilder(); int c = 0; boolean carriageReaded = false; //Indique si on a lu un retour chariot char lastCharacter = '\u0000'; while ((c = reader.read()) != -1) { char characterRead = (char) c; if (characterRead == '\r') { if (carriageReaded) { //On a lu le retour chariot deux fois consécutives donc on a pas de séparateur de ligne au sens windows //On ajoute les deux caractère à la chaîne que nous construisons line.append('\r').append(characterRead); carriageReaded = false; //On marque que la lecture d'une nouvelle ligne redémarre } else { // Première lecture du retour chariot carriageReaded = true; // On marque que nous avons lu un retour chariot } } else { if (carriageReaded) { // Le caractère précédemment lu c'est le retour chariot if (characterRead == '\n') { // Si le nouveau caractère lu est un saut de ligne c'est que nous venons de lire une nouvelle ligne //On effectue les traitements propres à la ligne String newLine = line.toString(); if (ParserUtils.characterOfDelimiteur(rawCsvData.getColumnDelimiter()) != '\0') { newLine = newLine.replaceAll(" {2,}", " "); } if (!withHeader) { //Représente les colonnes extraites de chaque ligne du fichier //String[] columnsTableLine = newLine.split(rawCsvData.getColumnDelimiter()); String[] columnsTableLine; if (rawCsvData.getColumnDelimiter().equals("\\t")) { columnsTableLine = ParserUtils.splitIntoColumns(newLine, '\t'); ResultFileParsing resultFileParsing = buildFinalColumnsTableLine(outputFile, columnsTableLine, mapParams, alphaNumeriqueToBeTruncated, numeroLigne.incrementAndGet(), truncateWriter); String[] finalColumnsTableLine = resultFileParsing.getFinalColumnsTableLine(); columnTruncated.set(resultFileParsing.isColumnTruncated()); String[] encodedStrings = ParserUtils.encodeStrings(finalColumnsTableLine, charset); ParserUtils.writeToFile(encodedStrings, bufferWriter); } else if (rawCsvData.getColumnDelimiter().isEmpty()) { parseLineUsingFieldLength(newLine, mapParams, rawCsvData.getColumnDelimiter(), bufferWriter, charset); } else { columnsTableLine = (newLine).split(rawCsvData.getColumnDelimiter()); ResultFileParsing resultFileParsing = buildFinalColumnsTableLine(outputFile, columnsTableLine, mapParams, alphaNumeriqueToBeTruncated, numeroLigne.incrementAndGet(), truncateWriter); String[] finalColumnsTableLine = resultFileParsing.getFinalColumnsTableLine(); if (!columnTruncated.get()) { columnTruncated.set(resultFileParsing.isColumnTruncated()); } String[] encodedStrings = ParserUtils.encodeStrings(finalColumnsTableLine, charset); ParserUtils.writeToFile(encodedStrings, bufferWriter); } //Nettoyage d'une colonne de chaque ligne } else { withHeader = false; } line = new StringBuilder(); //On réinitialise notre constructeur de ligne carriageReaded = false; //On marque que la lecture d'une nouvelle ligne redémarre } else { line.append(' '); //On change le saut de ligne par un espace } } else { if (characterRead == '\n') { if (lastCharacter != '\n') { line.append(' '); } } else { line.append(characterRead); } } } lastCharacter = characterRead; } } //Fermeture du writer } //Si au moins une colonne a été tronqué, alors copier le fichier dont les lignes ont été tronqué dans le répertoire d'archivage if (columnTruncated.get()) { Path originalFilePathInArchiveFolder = createOriginalFileInArchive(validateur, rawCsvData.getFile()); //Copie du fichier dont les colonnes ont été tronqués vers le répertoire archivage if (rawCsvData.getFile().exists()) { Files.copy(rawCsvData.getFile().toPath(), originalFilePathInArchiveFolder); } } else {//Sinon supprimer le fichier des éléments tronqués, car il est vide Files.deleteIfExists(pathOfTruncatedElts); } } } /** * Méthode qui extrait les données d'un fichier xlsx et les normalise * * @param validateur : Validateur du type fichier auquel appartient le * fichier à valider * @param outputFile : fichier texte généré en sortie * @param headerPresent : renseigne si le fichier a une ligne d'entête * @param alphaNumeriqueToBeTruncated : liste des champs à tronquer * @param filePath : Fichier qui contient les données à extraire * @throws IOException * @throws Exception */ public static void parseXlsxFile(String filePath, boolean headerPresent, File outputFile, Validateur validateur, Set alphaNumeriqueToBeTruncated) throws Exception { AtomicBoolean columnTruncated = new AtomicBoolean(); Path pathOfTruncatedElts = createTruncatedEltsPath(validateur, new File(filePath)); try ( InputStream is = new FileInputStream(filePath); Workbook wb = new XSSFWorkbook(is)) { parseExcelFile(filePath, wb, headerPresent, outputFile, validateur, alphaNumeriqueToBeTruncated, pathOfTruncatedElts); } treatTruncatedElements(filePath, pathOfTruncatedElts, validateur, columnTruncated); } public static void parseXlsFile(String filePath, boolean headerPresent, File outputFile, Validateur validateur, Set alphaNumeriqueToBeTruncated) throws Exception { AtomicBoolean columnTruncated = new AtomicBoolean(); Path pathOfTruncatedElts = createTruncatedEltsPath(validateur, new File(filePath)); try ( InputStream is = new FileInputStream(filePath); Workbook wb = new HSSFWorkbook(is)) { parseExcelFile(filePath, wb, headerPresent, outputFile, validateur, alphaNumeriqueToBeTruncated, pathOfTruncatedElts); } treatTruncatedElements(filePath, pathOfTruncatedElts, validateur, columnTruncated); } private static void parseExcelFile(String filePath, Workbook wb, boolean headerPresent, File outputFile, Validateur validateur, Set alphaNumeriqueToBeTruncated, Path pathOfTruncatedElts) throws IOException, Exception { Map mapParams = ParserUtils.getValidateurElements(validateur); final int maxPosition = Collections.max(mapParams.keySet()); AtomicInteger numeroLigne = new AtomicInteger(0); AtomicBoolean columnTruncated = new AtomicBoolean(); Charset charset = getCharset(new File(filePath)); try ( BufferedWriter bufferWriter = Files.newBufferedWriter(outputFile.toPath(), charset, StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.SYNC); BufferedWriter truncateWriter = Files.newBufferedWriter(pathOfTruncatedElts, Charset.defaultCharset(), StandardOpenOption.APPEND, StandardOpenOption.CREATE, StandardOpenOption.SYNC)) { for (int i = 0; i < wb.getNumberOfSheets(); i++) { Sheet sheet = wb.getSheetAt(i); AtomicInteger numberOfColumns = new AtomicInteger(0); AtomicBoolean withHeader = new AtomicBoolean(headerPresent); AtomicInteger lineNumber = new AtomicInteger(1); for (org.apache.poi.ss.usermodel.Row r : sheet) { if (!withHeader.get()) { for (int cn = 0; cn < r.getLastCellNum(); cn++) { numberOfColumns.incrementAndGet(); } //Représente les colonnes extraites de chaque ligne du fichier String[] columnsTableLine = new String[numberOfColumns.get()]; AtomicInteger index = new AtomicInteger(0); for (int cn = 0; cn < r.getLastCellNum(); cn++) { if (cn < maxPosition) { Map map = mapParams.get(index.get() + 1); //Prendre aussi les cellules vides en considération org.apache.poi.ss.usermodel.Cell c = r.getCell(cn, org.apache.poi.ss.usermodel.Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); String value = com.megatim.typefichier.validator.utilities.ParserUtils.getXlxsCellValue(c, wb, map.get(Constantes.LIBELLE_TYPE_DONNEE), map.get(Constantes.LIBELLE_FORMAT_DATE), map.get(Constantes.LIBELLE_SEPARATEUR_DATE), map.get(Constantes.ERROR_CODE)); columnsTableLine[index.get()] = value; index.incrementAndGet(); } else { break; } } try { //Nettoyage d'une colonne de chaque ligne ResultFileParsing resultFileParsing = buildFinalColumnsTableLine(outputFile, columnsTableLine, mapParams, alphaNumeriqueToBeTruncated, numeroLigne.incrementAndGet(), truncateWriter); String[] finalColumnsTableLine = resultFileParsing.getFinalColumnsTableLine(); columnTruncated.set(resultFileParsing.isColumnTruncated()); ParserUtils.writeToFile(finalColumnsTableLine, bufferWriter); } catch (Exception ex) { Logger.getLogger(ImportData.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } } else { withHeader.set(false); } lineNumber.incrementAndGet(); } } } } private static void treatTruncatedElements(String filePath, Path pathOfTruncatedElts, Validateur validateur, AtomicBoolean columnTruncated) throws IOException { //Si au moins une colonne a été tronqué, alors copier le fichier dont les lignes ont été tronqué dans le répertoire d'archivage if (columnTruncated.get()) { Path pathoriginalFilePath = Paths.get(filePath); Path originalFilePathInArchiveFolder = createOriginalFileInArchive(validateur, new File(filePath)); //Copie du fichier dont les colonnes ont été tronqués vers le répertoire archivage if (Files.exists(pathoriginalFilePath, LinkOption.NOFOLLOW_LINKS)) { Files.copy(pathoriginalFilePath, originalFilePathInArchiveFolder); } } else {//Sinon supprimer le fichier des éléments tronqués, car il est vide Files.deleteIfExists(pathOfTruncatedElts); } } /** * Méthode qui met les libellés des colonnes et leurs valeurs * correspondantes dans une map * * @param titles : ensemble des noms de colonnes * @param values : ensemble des données * @return : rentourne une map (clé,valeur) = (nom_de_la_colonne, * valeur_colonne) */ private static Map tabToMap(List titles, String[] values) { Map map = new HashMap<>(); for (int i = 0; i < titles.size(); i++) { map.put(titles.get(i), values[i]); } return map; } /** * Méthode qui met un tableau de Field dans une * map * afin de faciliter leur accès * * @param fields * @return */ private static Map fieldsToMap(Field[] fields) { Map map = new HashMap<>(); for (Field f : fields) { map.put(f.getName(), f); } return map; } /** * Méthode qui fait la conversion de la donnée extraite vers un type * primitif * * @param field : objet contenant les informations sur le type auquel * appartient le champ de la donnée extraite * @param value : donnée à convertir * @return : retourne un String si le type du champ ne figure pas dans la * liste ci-dessus */ private static Object convertToPrimitive(Field field, String value) { Object obj = value; if (field.getType().isAssignableFrom(Integer.class) || field.getType().isAssignableFrom(int.class)) { obj = Integer.valueOf(value); } else if (field.getType().isAssignableFrom(Double.class) || field.getType().isAssignableFrom(double.class)) { obj = Double.valueOf(value); } else if (field.getType().isAssignableFrom(java.math.BigDecimal.class)) { obj = new java.math.BigDecimal(value); } else if (field.getType().isAssignableFrom(Float.class) || field.getType().isAssignableFrom(float.class)) { obj = Float.valueOf(value); } else if (field.getType().isAssignableFrom(Long.class) || field.getType().isAssignableFrom(long.class)) { obj = Long.valueOf(value); } else if (field.getType().isAssignableFrom(Boolean.class) || field.getType().isAssignableFrom(boolean.class)) { Boolean.valueOf(value); } return obj; } /** * Méthode permettant de construire la donnée finale à écrire dans le * fichier texte * * @param outputFile * @param initialColumnsTableLine * @param mapParams * @param fieldsToBeTruncated * @param numeroLigne * @param truncateWriter * @return * @throws Exception */ private static ResultFileParsing buildFinalColumnsTableLine(File outputFile, String[] initialColumnsTableLine, Map mapParams, Set fieldsToBeTruncated, int numeroLigne, BufferedWriter truncateWriter) throws Exception { String[] finalColumnsTableLine = new String[mapParams.size() - 1]; String[] columnsTableLine = new String[mapParams.size() - 1]; //On copie les éléments à normaliser dans un nouveau tableau for (int j = 0; j < finalColumnsTableLine.length; j++) { //Arreter la copie si on atteint la fin du tableau initial if (j == initialColumnsTableLine.length) { j = finalColumnsTableLine.length; } else { final String result = initialColumnsTableLine[j] != null && !initialColumnsTableLine[j].isEmpty() ? Normalizer .normalize(initialColumnsTableLine[j], Normalizer.Form.NFD) //Retrait des caractères accentués .replaceAll("\\p{M}+", "") : ""; columnsTableLine[j] = result; } } //Type de données utilisé pour retourner le résultat de la construction des lignes de données ResultFileParsing resultFileParsing = new ResultFileParsing(); int index = 0; for (String str : columnsTableLine) { String columnTableLine = str != null ? str.trim() : ""; if (index < mapParams.size() - 1) { Map map = mapParams.get(index + 1); final int taille = Integer.parseInt(map.get(Constantes.LIBELLE_TAILLE)); String typeDonnee = map.get(Constantes.LIBELLE_TYPE_DONNEE); //Traitement d'une donnée de type décimal if (typeDonnee.equalsIgnoreCase(Constantes.LIBELLE_DECIMAL)) { finalColumnsTableLine[index] = normalizeDecimal(columnTableLine, map); //Traitement d'une donnée de type DATE } else if (typeDonnee.equalsIgnoreCase(Constantes.LIBELLE_DATE)) { if (columnTableLine.length() < taille) { finalColumnsTableLine[index] = generateUnknown(taille - columnTableLine.length(), " ") + columnTableLine; } else if (columnTableLine.length() == taille) { finalColumnsTableLine[index] = columnTableLine; } else { finalColumnsTableLine[index] = columnTableLine.substring(0, taille); } //Traitement d'une donnée de type NUMERIQUE } else if (typeDonnee.equalsIgnoreCase(Constantes.LIBELLE_NUMERIQUE)) { finalColumnsTableLine[index] = normalizeNumber(columnTableLine, taille); // } else if (typeDonnee.equalsIgnoreCase(Constantes.LIBELLE_ALPHANUMERIQUE)) { //Traitement d'une donnée de type ALPHANUMERIQUE if (columnTableLine.length() < taille) { finalColumnsTableLine[index] = generateUnknown(taille - columnTableLine.length(), " ") + columnTableLine; } else if (columnTableLine.length() == taille) { finalColumnsTableLine[index] = columnTableLine; } else { if (!fieldsToBeTruncated.isEmpty()) { //Récupérer l'index de début du champ en cours de traitement int indexDebutChamp = Integer.parseInt(map.get(Constantes.LIBELLE_INDEX)); //Mettre les champs à tronquer dans une liste afin d'y rechercher le champ en cours de traitement List liste = Arrays.asList(fieldsToBeTruncated.toArray(new AlphaNumeriqueField[0])) .stream().filter(a -> { // ici on vérifie si l'index de début du champ en cours de traitement correspond à l'index d'un des champs à tronquer //Car si 2 champs ont le même index, alors il s'agit d'un seul champ return a.getIndex() == indexDebutChamp; }).collect(Collectors.toList()); // Si on a trouvé un champ à tronquer qui a le même index que le champ courant alors, tronquer le champ boolean found = (liste.size() == 1); if (found) { AlphaNumeriqueField alphaField = liste.get(0); String finalData = columnTableLine.substring(0, taille); TruncatedElement truncatedElement = new TruncatedElement(alphaField.getValidateur().getCodeTypeFichier(), alphaField.getCodeColonne(), columnTableLine, finalData, outputFile.getName(), LocalDateTime.now(), numeroLigne, taille, columnTableLine.length()); // Journalisation du champs tronqués writeTruncatedElementsToFile(truncatedElement, truncateWriter); resultFileParsing.setColumnTruncated(true); finalColumnsTableLine[index] = finalData; } else { finalColumnsTableLine[index] = columnTableLine; } } else { finalColumnsTableLine[index] = columnTableLine; } } } else { finalColumnsTableLine[index] = columnTableLine; } } index++; } resultFileParsing.setFinalColumnsTableLine(finalColumnsTableLine); return resultFileParsing; } /** * Méthode qui normalise un nombre en ajoutant des zéros à gauche * * @param value * @param taille * @return */ private static String normalizeNumber(String value, int taille) { String newValue = value .trim() .replaceAll("\\s+", "") .replaceAll("\\u00A0", "")//nbsp .replaceAll(" ", "")//nbsp .replaceAll("\\p{Z}", "") .replaceAll("\t", "") .replaceAll("\r", "") .replaceAll("\n", ""); try { if (!newValue.matches("\\d+")) { newValue = new BigDecimal(newValue.replace(',', '.')).longValue() + "";//Remplacer la virgule par le point } } catch (Exception ex) { } return generateUnknown(taille - newValue.length(), " ") + newValue; } /** * Méthode qui normalise les nombres décimaux conformat aux tailles, en * ajoutant éventuellement des zéros à gauche de la partie entière et à * droite de la partie décimale renseignés dans le validateur * * @param value : chaîne à normaliser * @param map : map contenant les infos sur les parties entire et décimale * @return */ private static String normalizeDecimal(String value, Map map) { //Taille totale du nombre décimal int taille = Integer.parseInt(map.get(Constantes.LIBELLE_TAILLE)); int taillePartieDecimale = Integer.parseInt(map.get(Constantes.LIBELLE_TAILLE_PARTIE_DECIMALE)); String separateurDecimal = map.get(Constantes.LIBELLE_SEPARATEUR_DECIMAL); int tailleReelle = taille + taillePartieDecimale + separateurDecimal.trim().length(); String newValue = value.trim() .replaceAll("\\s+", "") .replaceAll("\\u00A0", "")//nbsp .replaceAll(" ", "")//nbsp .replaceAll("\\p{Z}", "") .replaceAll("\t", "") .replaceAll("\r", "") .replaceAll("\n", ""); if (newValue.length() >= tailleReelle) { return newValue; } if (newValue.matches("^\\d+[,.]?\\d+$") || newValue.matches("[-+]?\\d+(\\.\\d+)?[eE][-+]?\\d+") || newValue.matches("^\\d{1,3},\\d+E[+-]?\\d+$")) {//Notation scientifique try { newValue = new BigDecimal(newValue.replace(',', '.')).toPlainString();//Remplacer la virgule par le point } catch (Exception ex) { } } return generateUnknown(tailleReelle - newValue.length(), " ") + newValue; } /** * Méthode qui génère un nombre précis d'un quelconque caractère * * @param nbOfCharacter : nombre de fois à générer le caractère * @param character : caractère à générer * @return */ private static String generateUnknown(int nbOfCharacter, String character) { String str = ""; for (int i = 0; i < nbOfCharacter; i++) { str += character; } return str; } /** * Méthode qui extrait les données en se basant sur la taille des champs * définis dans le validateur */ private static void parseLineUsingFieldLength(String line, Map mapParams, String delimiteurColonne, BufferedWriter bufferWriter, Charset charset) throws IOException { String[] columnsTableLine = new String[mapParams.size() - 1]; try { int index = 0; int i = 1; while (i < mapParams.size()) { Map map = mapParams.get(i); int taille = Integer.parseInt(map.get(Constantes.LIBELLE_TAILLE)); if (i == mapParams.size() - 1) { columnsTableLine[i - 1] = line.substring(index); } else { columnsTableLine[i - 1] = line.substring(index, index + taille); } index = index + taille; //recupérer le charactère correspondant au delimiteur char character = ParserUtils.characterOfDelimiteur(delimiteurColonne); //Si le démimiteur n'est pas la chaîne vide if (character != '\0') { //Si on ne trouve pas le délimiteur après avoir lu le champ précédent, on arrete le traitement de cette ligne car fichier mal formaté if ((i < mapParams.size() - 1) && (line.charAt(index) != character)) { //Interrompre l'extraction des données en remplissant la condition de sortie de laboucle i = mapParams.size(); } else { //Incrementer l'index un afin de traverser le séparateur index = index + 1; } } i++; } String[] encodedStrings = ParserUtils.encodeStrings(columnsTableLine, charset); ParserUtils.writeToFile(encodedStrings, bufferWriter); } catch (Exception ex) { Logger.getLogger(ImportData.class.getName()).log(Level.SEVERE, ex.getMessage(), ex); } } /** * Méthode qui écrit les informations sur les éléments tronqués dans un * fichier * * @param t * @param bufferWriter * @throws IOException */ private static void writeTruncatedElementsToFile(TruncatedElement t, final BufferedWriter bufferWriter) throws IOException { //Ecriture dans le fichier output StringBuilder safeLineBuilder = new StringBuilder(0); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime date = t.getDateAction(); safeLineBuilder.append("Fichier:").append(t.getFileName()).append("|"); safeLineBuilder.append("Date:").append(date.format(formatter)).append("|"); safeLineBuilder.append("Ligne:").append(t.getLineNumber()).append("|"); safeLineBuilder.append("Colonne:").append(t.getCodeColonne()).append("|"); safeLineBuilder.append("Taille attendue:").append(t.getTailleAttendue()).append("|"); safeLineBuilder.append("Donnée finale:").append(t.getFinalData()).append("|"); safeLineBuilder.append("Taille trouvée:").append(t.getTailleTrouvee()).append("|"); safeLineBuilder.append("Donnée initiale:").append(t.getInitialData()); String safeLine = safeLineBuilder.toString(); if (safeLine.length() > 0) { bufferWriter.write(safeLine + System.lineSeparator()); } } /** * Méthode qui retourne le nom fichier sans extension * * @param file * @return */ private static String fileNameWithoutExtension(File file) { int index = file.getName().lastIndexOf("."); if (index > 0) { return file.getName().substring(0, index); } else { return file.getName(); } } /** * Méthode qui construit le chemin du fichier qui va contenit les logs des * éléments tronqués * * @param validateur * @param outputFile * @return * @throws IOException */ private static Path createTruncatedEltsPath(Validateur validateur, File outputFile) throws IOException { final String arhivageDirectory = ConfigurationService.getInstance().getCurrentConfig().getArchivesDir(); final String today = LocalDate.now().toString(); Path logDir = Paths.get(arhivageDirectory, today, validateur.getCodeTypeFichier(), "logs"); if (!Files.exists(logDir, LinkOption.NOFOLLOW_LINKS)) { Files.createDirectories(logDir); } Path pathOfTruncatedElts = Paths.get(arhivageDirectory, today, validateur.getCodeTypeFichier(), "logs", fileNameWithoutExtension(outputFile) + "_truncated_elements.txt"); return pathOfTruncatedElts; } /** * méthode permettant de construire le chemin du fichier d'origine dans le * répertoire d'archivages * * @param validateur * @param originalFile * @return * @throws IOException */ private static Path createOriginalFileInArchive(Validateur validateur, File originalFile) throws IOException { final String arhivageDirectory = ConfigurationService.getInstance().getCurrentConfig().getArchivesDir(); final String today = LocalDate.now().toString(); Path originalFilesDir = Paths.get(arhivageDirectory, today, validateur.getCodeTypeFichier(), "fichiers"); if (!Files.exists(originalFilesDir, LinkOption.NOFOLLOW_LINKS)) { Files.createDirectories(originalFilesDir); } Path originalFilePath = Paths.get(arhivageDirectory, today, validateur.getCodeTypeFichier(), "fichiers", originalFile.getName()); final String fileNameWithoutExtension = fileNameWithoutExtension(originalFile); //Si le fichier existe dans le répertoire d'archivages, alors ajouter un numero d'ordre dans son nom if (Files.exists(originalFilePath, LinkOption.NOFOLLOW_LINKS)) { List existingFiles = Files.list(originalFilesDir).filter(p -> p.toString().contains(fileNameWithoutExtension)).collect(Collectors.toList()); int nbFiles = existingFiles.size(); if (nbFiles > 0) { originalFilePath = Paths.get(arhivageDirectory, today, validateur.getCodeTypeFichier(), "fichiers", fileNameWithoutExtension + "(" + nbFiles + ")" + getFileExtension(originalFile)); } } return originalFilePath; } /** * Méthode qui retourne l'extension d'un fichier * * @param file * @return */ private static String getFileExtension(File file) { int index = file.getName().lastIndexOf("."); if (index <= 0) { return ""; } else { return file.getName().substring(index); } } }