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