From 8cbaa370347e6fc997381cf35d6c295685b90f98 Mon Sep 17 00:00:00 2001
From: Kenmegne <stephanie.kenmegne@gmail.com>
Date: Fri, 19 Jun 2026 11:29:14 +0000
Subject: [PATCH] move to new repo

---
 dynamicjsonparser/src/main/java/com/megatim/dynamicjsonparser/extender/JsonDataProcessor.java |  432 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 432 insertions(+), 0 deletions(-)

diff --git a/dynamicjsonparser/src/main/java/com/megatim/dynamicjsonparser/extender/JsonDataProcessor.java b/dynamicjsonparser/src/main/java/com/megatim/dynamicjsonparser/extender/JsonDataProcessor.java
new file mode 100644
index 0000000..f2a5454
--- /dev/null
+++ b/dynamicjsonparser/src/main/java/com/megatim/dynamicjsonparser/extender/JsonDataProcessor.java
@@ -0,0 +1,432 @@
+/*
+ * 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.dynamicjsonparser.extender;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.megatim.dynamicjsonparser.pojo.CustomError;
+import com.megatim.dynamicjsonparser.pojo.JsonField;
+import com.megatim.dynamicjsonparser.pojo.JsonParsedData;
+import com.megatim.dynamicjsonparser.pojo.Node;
+import com.megatim.dynamicjsonparser.pojo.Indexe;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.apache.commons.validator.GenericValidator;
+import org.burningwave.core.Virtual;
+import org.burningwave.core.classes.Constructors;
+
+/**
+ *
+ * @author ASUS
+ */
+public class JsonDataProcessor {
+
+    private final List<Node> nodes;
+    private final Class classOfEntity;
+    private final List<JsonField> jsonFields;
+    private final String rootClass;
+
+    private final JsonParsedData parsedData = new JsonParsedData();
+
+    public JsonDataProcessor(List<Node> nodes, Class classOfEntity, List<JsonField> jsonFields, String rootClass) {
+        this.nodes = nodes;
+        this.classOfEntity = classOfEntity;
+        this.jsonFields = jsonFields;
+        this.rootClass = rootClass;
+    }
+
+    public JsonParsedData iterateThroughNodes() {
+        for (Node node : nodes) {
+
+            Virtual virtualObject = traverseNode(node.getNode(), classOfEntity, jsonFields, Arrays.asList(new Indexe(node.getIndex())),
+                    rootClass);
+
+            //Ajout de l'objet extrait dans la liste
+            parsedData.getVirtuals().add(virtualObject);
+        }
+        return parsedData;
+    }
+
+    private JsonField retrieveField(List<JsonField> jsonFields, String fieldName) {
+        Optional<JsonField> optJsonField = jsonFields.stream().filter(j -> j.getName().equalsIgnoreCase(fieldName)).findFirst();
+        if (optJsonField.isPresent()) {
+            return optJsonField.get();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Méthode permettant de parcourir recursivement les noeuds du fichier json
+     *
+     * @param node : noeud à parcourir
+     * @param classOfEntity : classe Java du noeud à parcourir
+     * @param map : map contenant tous champs de la classe Java à utiliser lors
+     * de l'extraction
+     * @param indexes : tableau contenant la hiérarchie des index, cad les index
+     * permettant de déterminer la posotion précise du noeud dans le fichier
+     * @return
+     */
+    private Virtual traverseNode(final JsonNode node, final Class classOfEntity, final List<JsonField> jsonFields, List<Indexe> indexes, String fullQualifiedNameOfField) {
+        if (node != null && classOfEntity != null && jsonFields != null && !jsonFields.isEmpty()) {
+            Iterator<Map.Entry<String, JsonNode>> nodeFields = node.fields();
+            Virtual virtualObject = new Constructors().newInstanceOf(classOfEntity);
+            Set<String> foundFields = new HashSet<>();//contient les champs rencontrés dans chaque noeud json
+
+            Integer index = indexes.get(0).getPosition();
+
+            while (nodeFields.hasNext()) {
+
+                Map.Entry<String, JsonNode> entry = nodeFields.next();
+                final JsonField dynamicField = retrieveField(jsonFields, entry.getKey());
+
+                //Si c'est un attribut de l'objet en cours de traitement
+                if (dynamicField != null) {
+                    foundFields.add(entry.getKey());
+
+                    if (entry.getValue().toString().equals("null")) {//si la valeur du noeud est à null
+                        if (dynamicField.isRequired()) {
+                            parsedData.getErrors().add(requiredErrorMessage(entry.getKey(), fullQualifiedNameOfField, indexes));
+                        }
+                    } else {
+                        //Si la donnée que contient le noeud est un tableau
+                        if (entry.getValue().isArray() && entry.getValue().size() > 0) {
+
+                            JsonNode firstElement = entry.getValue().get(0);
+
+                            //Si c'est un tableau d'objets
+                            if (firstElement.isObject()) { //si c'est un tableau d'objets
+                                traverseArrayOfObjectNodes(virtualObject, entry, dynamicField, indexes, fullQualifiedNameOfField);
+                            } else {
+                                traverseArrayOfTextualNodes(virtualObject, entry, dynamicField, indexes, fullQualifiedNameOfField);
+                            }
+                        } else if (entry.getValue().isObject()) {
+                            traverseSingleObjectNode(virtualObject, entry, dynamicField, indexes, fullQualifiedNameOfField);
+                        } else {
+                            traverseSingleTextualNode(virtualObject, entry, dynamicField, indexes, fullQualifiedNameOfField);
+                        }
+                    }
+                } else {
+                    CustomError customError = constructErrorMessage(indexes);
+                    customError.getMessage().append("Attribut ").append("\"").append(fullQualifiedNameOfField).append(".").append(entry.getKey()).append("\"")
+                            .append(" inexistant dans la définition de l'entité ").append("\"")
+                            .append(jsonFields.get(0).getClassName())
+                            .append("\"");
+                    parsedData.getErrors().add(customError);
+                }
+
+            }
+            //Vérifier si des champs obligatoirs sont absents
+            checkIfRequiredFieldIsAbsent(foundFields, jsonFields, indexes, fullQualifiedNameOfField);
+            index++;
+
+            return virtualObject;
+        } else {
+            return null;
+        }
+    }
+
+    private void checkIfRequiredFieldIsAbsent(Set<String> foundFields, final List<JsonField> jsonFields, List<Indexe> indexes, String fullQualifiedNameOfField) {
+        jsonFields.forEach(j -> {
+            if (j.isRequired() && !foundFields.stream().filter(f->f.equalsIgnoreCase(j.getName())).findFirst().isPresent()) {
+                parsedData.getErrors().add(requiredErrorMessage(j.getName(), fullQualifiedNameOfField, indexes));
+            }
+        });
+    }
+
+    private CustomError requiredErrorMessage(String key, String fullQualifiedNameOfField, List<Indexe> indexes) {
+        CustomError customError = constructErrorMessage(indexes);
+        customError.getMessage().append("La valeur de l'attribut ").append("\"").append(fullQualifiedNameOfField).append(".").append(key).append("\"")
+                .append(" ne peut être nulle ");
+
+        return customError;
+    }
+
+    private void traverseArrayOfTextualNodes(Virtual virtualObject, Map.Entry<String, JsonNode> entry, JsonField dynamicField, List<Indexe> indexes, String fullQualifiedNameOfField) {
+
+        if (entry.getValue().toString().equals("null") || entry.getValue().size() == 0) {
+            if (dynamicField.isRequired()) {
+                parsedData.getErrors().add(requiredErrorMessage(entry.getKey(), fullQualifiedNameOfField, indexes));
+            }
+            return;
+        }
+        Class classOfField = dynamicField.getClazz();
+        CustomError customError = constructErrorMessage(indexes);
+        customError.getMessage().append("\"").append(fullQualifiedNameOfField).append(".").append(entry.getKey()).append("\"").append(" {");
+
+        boolean isTextFormatted = true;
+        List<Object> values = new ArrayList<>();
+
+        //On valide chaque élément du tableau
+        for (int i = 0; i < entry.getValue().size(); i++) {
+            Object finalObject = validateValue(entry.getValue().get(i).asText(), dynamicField);
+
+            //Si l'objet retourné après validation est nul, alors la validation a échoué
+            if (finalObject == null) {
+                customError.getMessage().append(" Elément N°").append(i + 1).append(" est mal formaté").append(", ");//On renseigne la position de l'élément qui a échoué
+                isTextFormatted = false;
+
+            } else if (finalObject.toString().length() > dynamicField.getLengthh()) {
+                customError.getMessage().append(" Elément N°").append(i + 1).append(" La taille de la donnée est supérieure à la taille attendue").append(", ");//On renseigne la position de l'élément qui a échoué
+                isTextFormatted = false;
+            }
+            values.add(finalObject);// ajouter l'élément au tableau final
+        }
+
+        if (!isTextFormatted) {
+            customError.getMessage().replace(customError.getMessage().length() - 2, customError.getMessage().length(), " }");
+            parsedData.getErrors().add(customError);
+        }
+
+        List finalValues = convertToRealType(values, classOfField);
+        virtualObject.invoke(setterofField(dynamicField.getName()), finalValues);
+    }
+
+    private void traverseArrayOfObjectNodes(Virtual virtualObject, Map.Entry<String, JsonNode> entry, JsonField dynamicField, List<Indexe> indexes, String fullQualifiedNameOfField) {
+        if (entry.getValue().toString().equals("null") || entry.getValue().size() == 0) {
+            if (dynamicField.isRequired()) {
+                parsedData.getErrors().add(requiredErrorMessage(entry.getKey(), fullQualifiedNameOfField, indexes));
+            }
+            return;
+        }
+        List<Virtual> virtuals = new ArrayList<>();
+        List<Indexe> subIndexes = new ArrayList<>();
+        subIndexes.addAll(indexes);
+
+        subIndexes.add(new Indexe(1, fullQualifiedNameOfField + "." + entry.getKey()));
+
+        for (int i = 0; i < entry.getValue().size(); i++) {
+
+            //Valider de façon récursive les objets du tableau
+            virtuals.add(traverseNode(entry.getValue().get(i), dynamicField.getClazz(), dynamicField.getDynamicFields(), subIndexes, fullQualifiedNameOfField + "." + entry.getKey()));
+
+            int subPosition = subIndexes.get(subIndexes.size() - 1).getPosition();
+            subIndexes.get(subIndexes.size() - 1).setPosition(subPosition + 1);
+        }
+
+        virtualObject.invoke(setterofField(dynamicField.getName()), virtuals);
+    }
+
+    private void traverseSingleTextualNode(Virtual virtualObject, Map.Entry<String, JsonNode> entry, JsonField dynamicField, List<Indexe> indexes, String fullQualifiedNameOfField) {
+        if (entry.getValue().toString().equals("null") || entry.getValue().asText().isEmpty()) {
+            if (dynamicField.isRequired()) {
+                parsedData.getErrors().add(requiredErrorMessage(entry.getKey(), fullQualifiedNameOfField, indexes));
+            }
+            return;
+        }
+        Object finalValue = validateValue(entry.getValue().asText(), dynamicField);
+
+        if (finalValue == null) {
+            CustomError customError = constructErrorMessage(indexes);
+            customError.getMessage().append("\"").append(fullQualifiedNameOfField).append(".").append(entry.getKey()).append("\"").append(" est mal formaté");
+            parsedData.getErrors().add(customError);
+
+        } else if (finalValue.toString().length() > dynamicField.getLengthh()) {
+            CustomError customError = constructErrorMessage(indexes);
+            customError.getMessage().append("\"").append(fullQualifiedNameOfField).append(".").append(entry.getKey()).append("\"").append(" La taille de la donnée est supérieure à la taille attendue");
+            parsedData.getErrors().add(customError);
+        } else {
+            virtualObject.invoke(setterofField(dynamicField.getName()), finalValue);
+        }
+    }
+
+    private void traverseSingleObjectNode(Virtual virtualObject, Map.Entry<String, JsonNode> entry, JsonField dynamicField, List<Indexe> indexes, String fullQualifiedNameOfField) {
+        List<Indexe> subIndexes = new ArrayList<>();
+        subIndexes.addAll(indexes);
+        subIndexes.add(new Indexe(entry.getKey()));
+
+        if (entry.getValue().toString().equals("null")) {
+            if (dynamicField.isRequired()) {
+                parsedData.getErrors().add(requiredErrorMessage(entry.getKey(), fullQualifiedNameOfField, indexes));
+            }
+            return;
+        }
+        Virtual virtual = traverseNode(entry.getValue(), dynamicField.getClazz(), dynamicField.getDynamicFields(), subIndexes, fullQualifiedNameOfField + "." + entry.getKey());
+
+        virtualObject.invoke(setterofField(dynamicField.getName()), virtual);
+    }
+
+    private boolean validateDate(String value, String formatDate, String separateurDate) {
+        boolean result = false;
+
+        StringBuilder dateToValidate = new StringBuilder(0);
+
+        if (separateurDate != null && !separateurDate.isEmpty()) {
+
+            String[] dateArray = value.split(separateurDate);
+
+            for (String d : dateArray) {
+                dateToValidate.append(d);
+            }
+        } else {
+            dateToValidate = new StringBuilder(value);
+        }
+
+        if (formatDate != null && !formatDate.isEmpty()) {
+            result = GenericValidator.isDate(dateToValidate.toString(), formatDate, false);
+        }
+        return result;
+    }
+
+    /**
+     * Méthode qui validate une donnée
+     *
+     * @param value
+     * @param classOfField
+     * @return
+     */
+    private Object validateValue(String value, JsonField dynamicField) {
+        Object finalValue = null;
+        Class classOfField = dynamicField.getClazz();
+
+        try {
+            if (classOfField.isAssignableFrom(LocalDate.class)) {
+
+                boolean isFormatted = validateDate(value, dynamicField.getFormatDate(), dynamicField.getSeparateurDate());
+
+                if (isFormatted) {
+                    finalValue = value;
+                }
+
+            } else if (classOfField.isAssignableFrom(Long.class)) {
+
+                finalValue = Long.valueOf(value);
+            } else if (classOfField.isAssignableFrom(BigDecimal.class)) {
+                finalValue = new BigDecimal(value);
+
+            } else {
+                finalValue = value;
+            }
+        } catch (Exception ex) {
+        }
+        return finalValue;
+    }
+
+    private List<LocalDate> convertListOfDate(List<Object> genericValues) {
+        List<LocalDate> listeLocalDate = new ArrayList<>();
+
+        genericValues.forEach(g -> {
+
+            LocalDate localDate = null;
+
+            if (g != null) {
+                localDate = (LocalDate) g;
+            }
+
+            listeLocalDate.add(localDate);
+        });
+        return listeLocalDate;
+    }
+
+    private List<Long> convertListOfLong(List<Object> genericValues) {
+        List<Long> listeLong = new ArrayList<>();
+
+        genericValues.forEach(g -> {
+
+            Long longValue = null;
+
+            if (g != null) {
+                longValue = (Long) g;
+            }
+            listeLong.add(longValue);
+        });
+
+        return listeLong;
+    }
+
+    private List<BigDecimal> convertListOfBigDecimal(List<Object> genericValues) {
+        List<BigDecimal> listeBigDecimal = new ArrayList<>();
+
+        genericValues.forEach(g -> {
+
+            BigDecimal bigDecimalValue = null;
+
+            if (g != null) {
+                bigDecimalValue = (BigDecimal) g;
+            }
+
+            listeBigDecimal.add(bigDecimalValue);
+        });
+
+        return listeBigDecimal;
+    }
+
+    private List<String> convertListOfString(List<Object> genericValues) {
+        List<String> listeString = new ArrayList<>();
+
+        genericValues.forEach(g -> {
+
+            String str = null;
+
+            if (g != null) {
+                str = (String) g;
+            }
+
+            listeString.add(str);
+        });
+        return listeString;
+    }
+
+    /**
+     * Méthode qui converti une liste d'objets en une liste d'un type précis
+     *
+     * @param genericValues
+     * @param classOfField
+     * @return
+     */
+    private List convertToRealType(List<Object> genericValues, Class classOfField) {
+
+        if (classOfField.isAssignableFrom(LocalDate.class)) {
+            return convertListOfDate(genericValues);
+
+        } else if (classOfField.isAssignableFrom(Long.class)) {
+            return convertListOfLong(genericValues);
+
+        } else if (classOfField.isAssignableFrom(BigDecimal.class)) {
+            return convertListOfBigDecimal(genericValues);
+
+        } else {
+            return convertListOfString(genericValues);
+        }
+    }
+
+    private CustomError constructErrorMessage(List<Indexe> indexes) {
+        StringBuilder error = new StringBuilder();
+        CustomError customError = new CustomError();
+        customError.setEltNumber(indexes.get(0).getPosition());
+
+        indexes.forEach(indexe -> {
+
+            if (indexe.getFullQualifiedNameOfField() != null && !indexe.getFullQualifiedNameOfField().isEmpty() && indexe.getPosition() != 0) {
+                error.append("\"").append(indexe.getFullQualifiedNameOfField()).append("\"").append(" : ").append("Elément N° ").append(indexe.getPosition()).append(" : ");
+
+            } else if (indexe.getFullQualifiedNameOfField() != null && !indexe.getFullQualifiedNameOfField().isEmpty()) {
+                error.append("\"").append(indexe.getFullQualifiedNameOfField()).append("\"").append(" : ");
+
+            } else if (indexe.getPosition() != 0) {
+                error.append("Elément N° ").append(indexe.getPosition()).append(" : ");
+            }
+        });
+
+        customError.setMessage(error);
+        return customError;
+    }
+
+    private static String setterofField(String fieldName) {
+
+        String name = String.valueOf(fieldName.charAt(0)).toUpperCase() + fieldName.substring(1);
+
+        return "set" + name;
+    }
+}

--
Gitblit v1.10.0