From b3d0580439b9a00c7eb918085de1694151066004 Mon Sep 17 00:00:00 2001
From: Kenmegne <stephanie.kenmegne@gmail.com>
Date: Thu, 18 Jun 2026 16:02:49 +0000
Subject: [PATCH] rename packages

---
 fdx_convert/src/main/java/com/megatim/fdxconvert/util/ImportData.java | 1138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,138 insertions(+), 0 deletions(-)

diff --git a/fdx_convert/src/main/java/com/megatim/fdxconvert/util/ImportData.java b/fdx_convert/src/main/java/com/megatim/fdxconvert/util/ImportData.java
new file mode 100644
index 0000000..b928edd
--- /dev/null
+++ b/fdx_convert/src/main/java/com/megatim/fdxconvert/util/ImportData.java
@@ -0,0 +1,1138 @@
+/*
+ * 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 <T>
+     * @param datIm
+     * @return
+     * @throws java.lang.Exception
+     */
+    public static <T> List<T> importDataFromCsvFile(DataToImport<T> datIm) throws Exception {
+
+//        FileReader reader = null;
+        List<String[]> datas = new ArrayList<>();
+
+        List<T> 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<String, Field> fieldsToMap = fieldsToMap(fields);
+
+                datas.forEach(d -> {
+
+                    try {
+
+                        T obj = datIm.getType().newInstance();
+
+                        Map<String, String> 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<AlphaNumeriqueField> alphaNumeriqueToBeTruncated) throws Exception {
+
+        Map<Integer, 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<Integer, 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<AlphaNumeriqueField> alphaNumeriqueToBeTruncated) throws Exception {
+
+        Map<Integer, 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<AlphaNumeriqueField> 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<AlphaNumeriqueField> 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<AlphaNumeriqueField> alphaNumeriqueToBeTruncated, Path pathOfTruncatedElts) throws IOException, Exception {
+        Map<Integer, 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<String, String> 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<String, String> tabToMap(List<String> titles, String[] values) {
+        Map<String, String> 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<nom_du_champ,objet représentant_le_champ>
+     * afin de faciliter leur accès
+     *
+     * @param fields
+     * @return
+     */
+    private static Map<String, Field> fieldsToMap(Field[] fields) {
+        Map<String, Field> 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<Integer, Map> mapParams, Set<AlphaNumeriqueField> 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<String, String> 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<AlphaNumeriqueField> 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;", "")//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<String, String> 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;", "")//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<Integer, 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<String, String> 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<Path> 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);
+        }
+    }
+
+}

--
Gitblit v1.10.0