From a8b99173f6b3366c6c858502baa0142116ebf096 Mon Sep 17 00:00:00 2001
From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr>
Date: Mon, 28 Feb 2022 10:59:51 +0100
Subject: [PATCH 1/6] Ajout du type SQL COMPOSITE_DATE
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Création d'un type composite COMPOSITE_DATE(timestamp,Text)
Contient
- le timestamp d'une date 01/01/1970 pour les heures
- la chaine formattée

Ajout de cast
- text::COMPOSITE_DATE pour caster une chaine en COMPOSITE_DATE (le texte doit correspondre à un timestamp POSTGRESQL)
- COMPOSITE_DATE::Timestamp revoit le timestamp da la COMPOSITE_DATE
- COMPOSITE_DATE::text renvoie le texte formatté

Modification de la date utilisée dans le cas d'un time (1/1/1970)

Attention il y a incompatibilté des timestamps iso de javascript/java/postgresql. On stocke dans le json le timestamp javascript sur 14 caractères.
Pas de problème pour les dates entre les années 1000 et 9999
---
 .../inra/oresing/checker/DateLineChecker.java |   2 +-
 .../oresing/persistence/SqlPrimitiveType.java |   5 +-
 .../fr/inra/oresing/rest/OreSiService.java    | 106 +++++-------------
 .../inra/oresing/rest/RelationalService.java  |  17 ++-
 .../DateValidationCheckResult.java            |   6 +-
 .../migration/main/V1__init_schema.sql        |  27 ++++-
 6 files changed, 74 insertions(+), 89 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/checker/DateLineChecker.java b/src/main/java/fr/inra/oresing/checker/DateLineChecker.java
index b1ba76f25..7e1e2b252 100644
--- a/src/main/java/fr/inra/oresing/checker/DateLineChecker.java
+++ b/src/main/java/fr/inra/oresing/checker/DateLineChecker.java
@@ -81,6 +81,6 @@ public class DateLineChecker implements CheckerOnOneVariableComponentLineChecker
 
     @Override
     public SqlPrimitiveType getSqlType() {
-        return SqlPrimitiveType.TEXT;
+        return SqlPrimitiveType.COMPOSITE_DATE;
     }
 }
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/persistence/SqlPrimitiveType.java b/src/main/java/fr/inra/oresing/persistence/SqlPrimitiveType.java
index 2911e1c6e..1d48096ee 100644
--- a/src/main/java/fr/inra/oresing/persistence/SqlPrimitiveType.java
+++ b/src/main/java/fr/inra/oresing/persistence/SqlPrimitiveType.java
@@ -7,7 +7,8 @@ public enum SqlPrimitiveType {
     UUID,
     TEXT,
     INTEGER,
-    NUMERIC;
+    NUMERIC,
+    COMPOSITE_DATE;
 
     /**
      * Le type en SQL, tel qu'il faut l'écrire pour faire un cast
@@ -24,4 +25,4 @@ public enum SqlPrimitiveType {
     public boolean isEmptyStringValidValue() {
         return this == TEXT;
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/OreSiService.java b/src/main/java/fr/inra/oresing/rest/OreSiService.java
index 43c596da0..76698f058 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiService.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java
@@ -3,76 +3,23 @@ package fr.inra.oresing.rest;
 import com.google.common.base.Charsets;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultiset;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Iterators;
-import com.google.common.collect.LinkedListMultimap;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Maps;
-import com.google.common.collect.MoreCollectors;
-import com.google.common.collect.Ordering;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
+import com.google.common.collect.*;
 import com.google.common.primitives.Ints;
 import fr.inra.oresing.OreSiTechnicalException;
 import fr.inra.oresing.ValidationLevel;
-import fr.inra.oresing.checker.CheckerFactory;
-import fr.inra.oresing.checker.DateLineChecker;
-import fr.inra.oresing.checker.FloatChecker;
-import fr.inra.oresing.checker.IntegerChecker;
-import fr.inra.oresing.checker.InvalidDatasetContentException;
-import fr.inra.oresing.checker.LineChecker;
-import fr.inra.oresing.checker.Multiplicity;
-import fr.inra.oresing.checker.ReferenceLineChecker;
-import fr.inra.oresing.checker.ReferenceLineCheckerConfiguration;
+import fr.inra.oresing.checker.*;
 import fr.inra.oresing.groovy.CommonExpression;
 import fr.inra.oresing.groovy.Expression;
 import fr.inra.oresing.groovy.GroovyContextHelper;
 import fr.inra.oresing.groovy.StringGroovyExpression;
-import fr.inra.oresing.model.Application;
-import fr.inra.oresing.model.Authorization;
-import fr.inra.oresing.model.BinaryFile;
-import fr.inra.oresing.model.BinaryFileDataset;
-import fr.inra.oresing.model.Configuration;
-import fr.inra.oresing.model.Data;
-import fr.inra.oresing.model.Datum;
-import fr.inra.oresing.model.LocalDateTimeRange;
-import fr.inra.oresing.model.ReferenceColumn;
-import fr.inra.oresing.model.ReferenceColumnMultipleValue;
-import fr.inra.oresing.model.ReferenceColumnSingleValue;
-import fr.inra.oresing.model.ReferenceColumnValue;
-import fr.inra.oresing.model.ReferenceDatum;
-import fr.inra.oresing.model.ReferenceValue;
-import fr.inra.oresing.model.VariableComponentKey;
+import fr.inra.oresing.model.*;
 import fr.inra.oresing.model.internationalization.Internationalization;
 import fr.inra.oresing.model.internationalization.InternationalizationDisplay;
 import fr.inra.oresing.model.internationalization.InternationalizationReferenceMap;
-import fr.inra.oresing.persistence.AuthenticationService;
-import fr.inra.oresing.persistence.BinaryFileInfos;
-import fr.inra.oresing.persistence.DataRepository;
-import fr.inra.oresing.persistence.DataRow;
-import fr.inra.oresing.persistence.Ltree;
-import fr.inra.oresing.persistence.OreSiRepository;
-import fr.inra.oresing.persistence.ReferenceValueRepository;
-import fr.inra.oresing.persistence.SqlPolicy;
-import fr.inra.oresing.persistence.SqlSchema;
-import fr.inra.oresing.persistence.SqlSchemaForApplication;
-import fr.inra.oresing.persistence.SqlService;
+import fr.inra.oresing.persistence.*;
 import fr.inra.oresing.persistence.roles.OreSiRightOnApplicationRole;
 import fr.inra.oresing.persistence.roles.OreSiUserRole;
-import fr.inra.oresing.rest.validationcheckresults.DateValidationCheckResult;
-import fr.inra.oresing.rest.validationcheckresults.DefaultValidationCheckResult;
-import fr.inra.oresing.rest.validationcheckresults.DuplicationLineValidationCheckResult;
-import fr.inra.oresing.rest.validationcheckresults.MissingParentLineValidationCheckResult;
-import fr.inra.oresing.rest.validationcheckresults.ReferenceValidationCheckResult;
+import fr.inra.oresing.rest.validationcheckresults.*;
 import fr.inra.oresing.transformer.TransformerFactory;
 import lombok.Value;
 import lombok.extern.slf4j.Slf4j;
@@ -104,21 +51,7 @@ import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -382,8 +315,9 @@ public class OreSiService {
 
     public UUID addReference(Application app, String refType, MultipartFile file) throws IOException {
         ReferenceValueRepository referenceValueRepository = repo.getRepository(app).referenceValue();
+        Map<ReferenceColumn, DateValidationCheckResult> dateValidationCheckResultImmutableMap = new HashMap<>();
         authenticationService.setRoleForClient();
-        UUID fileId = storeFile(app, file,"");
+        UUID fileId = storeFile(app, file, "");
 
         Configuration conf = app.getConfiguration();
         Configuration.ReferenceDescription ref = conf.getReferences().get(refType);
@@ -491,7 +425,21 @@ public class OreSiService {
                         ReferenceDatum referenceDatum = ReferenceDatum.copyOf(referenceDatumBeforeChecking);
                         lineCheckers.forEach(lineChecker -> {
                             Set<ValidationCheckResult> validationCheckResults = lineChecker.checkReference(referenceDatumBeforeChecking);
-                            if (lineChecker instanceof ReferenceLineChecker) {
+                            if (lineChecker instanceof DateLineChecker) {
+                                validationCheckResults.forEach(validationCheckResult -> {
+                                    final DateLineChecker dateLineChecker = (DateLineChecker) lineChecker;
+                                    final DateValidationCheckResult dateValidationCheckResult = (DateValidationCheckResult) validationCheckResult;
+                                    final ReferenceColumnValue referenceColumnValue = referenceDatum.get((ReferenceColumn) dateValidationCheckResult.getTarget());
+                                     referenceDatum.put(
+                                             (ReferenceColumn) dateValidationCheckResult.getTarget(),
+                                             referenceDatumBeforeChecking.get((ReferenceColumn) dateValidationCheckResult.getTarget())
+                                                     .transform(v ->
+                                                     String.format("date:%s:%s",dateValidationCheckResult.getMessage(), v)
+                                                     )
+                                     );
+
+                                });
+                            } else if (lineChecker instanceof ReferenceLineChecker) {
                                 ReferenceLineChecker referenceLineChecker = (ReferenceLineChecker) lineChecker;
                                 ReferenceColumn referenceColumn = (ReferenceColumn) referenceLineChecker.getTarget().getTarget();
                                 SetMultimap<ReferenceColumn, String> rawValueReplacedByKeys = HashMultimap.create();
@@ -633,8 +581,8 @@ public class OreSiService {
                     String naturalKey = ref.getKeyColumns()
                             .stream()
                             .map(kc -> columns.indexOf(kc))
-                            .map(k -> Strings.isNullOrEmpty(csvrecord.get(k))?null:Ltree.escapeToLabel(csvrecord.get(k)))
-                            .filter(k->k!=null)
+                            .map(k -> Strings.isNullOrEmpty(csvrecord.get(k)) ? null : Ltree.escapeToLabel(csvrecord.get(k)))
+                            .filter(k -> k != null)
                             .collect(Collectors.joining("__"));
                     if (!referenceUUIDs.containsKey(naturalKey)) {
                         referenceUUIDs.put(naturalKey, UUID.randomUUID());
@@ -844,7 +792,7 @@ public class OreSiService {
                 .orElseGet(() -> {
                     UUID fileId = null;
                     try {
-                        fileId = storeFile(app, file,"");
+                        fileId = storeFile(app, file, "");
                     } catch (IOException e) {
                         return null;
                     }
@@ -1633,4 +1581,4 @@ public class OreSiService {
         int lineNumber;
         List<Map.Entry<String, String>> columns;
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/RelationalService.java b/src/main/java/fr/inra/oresing/rest/RelationalService.java
index a37860fdd..d3446cc64 100644
--- a/src/main/java/fr/inra/oresing/rest/RelationalService.java
+++ b/src/main/java/fr/inra/oresing/rest/RelationalService.java
@@ -341,11 +341,20 @@ public class RelationalService implements InitializingBean, DisposableBean {
                     .map(referenceColumn -> {
                         String columnName = quoteSqlIdentifier(referenceColumn.getColumn());
                         SqlPrimitiveType columnType = sqlTypePerColumns.getOrDefault(referenceColumn, SqlPrimitiveType.TEXT);
-                        String columnDeclaration = String.format("%s %s", columnName, columnType.getSql());
+                        String columnDeclaration = String.format("%s %s", columnName, SqlPrimitiveType.TEXT);
                         return columnDeclaration;
                     })
                     .collect(Collectors.joining(", ", "(", ")"));
             String quotedReferenceType = quoteSqlIdentifier(referenceType);
+            String castedColumnSelect = columns.stream()
+                    .map(ReferenceColumn::new)
+                    .map(referenceColumn -> {
+                        String columnName = quoteSqlIdentifier(referenceColumn.getColumn());
+                        SqlPrimitiveType columnType = sqlTypePerColumns.getOrDefault(referenceColumn, SqlPrimitiveType.TEXT);
+                        String columnDeclaration = String.format("%s.%s::%s\n", quotedReferenceType,columnName, columnType.getSql());
+                        return columnDeclaration;
+                    })
+                    .collect(Collectors.joining(", "));
 
             // par exemple "projet"(nom_en text, nom_fr text, nom_key text, definition_en text, definition_fr text)
             String schemaDeclaration = quotedReferenceType + columnsAsSchema;
@@ -354,8 +363,10 @@ public class RelationalService implements InitializingBean, DisposableBean {
             String quotedViewHierarchicalKeyColumnName = quoteSqlIdentifier(referenceType + "_hierarchicalKey");
             String quotedViewNaturalKeyColumnName = quoteSqlIdentifier(referenceType + "_naturalKey");
             String referenceValueTableName = SqlSchema.forApplication(app).referenceValue().getSqlIdentifier();
-            String referenceView = "select referenceValue.id as " + quotedViewIdColumnName + ", referenceValue.hierarchicalKey as " + quotedViewHierarchicalKeyColumnName + ", referenceValue.naturalKey as " + quotedViewNaturalKeyColumnName + ", " + quotedReferenceType + ".* "
-                    + " from " + referenceValueTableName + ", jsonb_to_record(referenceValue.refValues) as " + schemaDeclaration
+            String referenceView = "select referenceValue.id as " + quotedViewIdColumnName + ", referenceValue.hierarchicalKey as " + quotedViewHierarchicalKeyColumnName + ", referenceValue.naturalKey as " + quotedViewNaturalKeyColumnName + ", "
+                    + castedColumnSelect
+                    + " from " + referenceValueTableName + ", " +
+                    "jsonb_to_record(referenceValue.refValues) as " + schemaDeclaration
                     + " where referenceType = '" + referenceType + "' and application = '" + appId + "'::uuid";
 
             if (log.isTraceEnabled()) {
diff --git a/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java b/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java
index 8bf361a4f..4debb3776 100644
--- a/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java
+++ b/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java
@@ -42,17 +42,17 @@ public class DateValidationCheckResult implements ValidationCheckResult {
                 ))
                 .orElse(null);
         this.date = (TemporalAccessor) Optional.ofNullable(messageParams).map(mp->mp.getOrDefault(DateLineChecker.PARAM_DATE, null)).orElse(null);
-        LocalDateTime localDateTime = LocalDateTime.MIN;
+        LocalDateTime localDateTime = null;
         if(date!=null){
             LocalDate localdate = date.query(TemporalQueries.localDate());
-            localdate=localdate==null?LocalDate.MIN:localdate;
+            localdate=localdate==null?LocalDate.of(1970, 1, 1):localdate;
             LocalTime localTime = date.query(TemporalQueries.localTime());
             localTime=localTime==null?LocalTime.MIN:localTime;
             localDateTime = localdate.atTime(localTime);
         }
 
 
-        this.message = localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
+        this.message = localDateTime==null?null:localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
     }
 
     public static DateValidationCheckResult success(Map<String, Object> params) {
diff --git a/src/main/resources/migration/main/V1__init_schema.sql b/src/main/resources/migration/main/V1__init_schema.sql
index 9222f240c..a7126613f 100644
--- a/src/main/resources/migration/main/V1__init_schema.sql
+++ b/src/main/resources/migration/main/V1__init_schema.sql
@@ -199,4 +199,29 @@ CREATE POLICY "applicationCreator_Application_select" ON Application AS PERMISSI
             USING ( true );
 
 CREATE AGGREGATE jsonb_object_agg(jsonb) (SFUNC = 'jsonb_concat', STYPE = jsonb, INITCOND = '{}');
-CREATE AGGREGATE aggregate_by_array_concatenation(anyarray) (SFUNC = 'array_cat', STYPE = anyarray, INITCOND = '{}');
\ No newline at end of file
+CREATE AGGREGATE aggregate_by_array_concatenation(anyarray) (SFUNC = 'array_cat', STYPE = anyarray, INITCOND = '{}');
+
+create type COMPOSITE_DATE as (
+  datetimestamp           "timestamp",
+  formattedDate           "varchar"
+) ;
+CREATE FUNCTION castTextToCompositeDate(Text) RETURNS COMPOSITE_DATE AS
+ 'select
+        (substring($1 from 6 for 19)::timestamp,
+         substring($1 from 26))::COMPOSITE_DATE;'
+    LANGUAGE SQL
+    IMMUTABLE
+    RETURNS NULL ON NULL INPUT;
+CREATE CAST (TEXT AS COMPOSITE_DATE) WITH FUNCTION castTextToCompositeDate(Text) AS ASSIGNMENT;
+CREATE FUNCTION castCompositeDateToTimestamp(COMPOSITE_DATE) RETURNS TIMESTAMP
+AS 'select ($1).datetimestamp;'
+    LANGUAGE SQL
+    IMMUTABLE
+    RETURNS NULL ON NULL INPUT;
+CREATE CAST (COMPOSITE_DATE AS TIMESTAMP) WITH FUNCTION castCompositeDateToTimestamp(COMPOSITE_DATE) AS ASSIGNMENT;
+CREATE FUNCTION castCompositeDateToFormattedDate(COMPOSITE_DATE) RETURNS Text
+AS 'select ($1).formattedDate;'
+    LANGUAGE SQL
+    IMMUTABLE
+    RETURNS NULL ON NULL INPUT;
+CREATE CAST (COMPOSITE_DATE AS Text) WITH FUNCTION castCompositeDateToFormattedDate(COMPOSITE_DATE) AS ASSIGNMENT;
\ No newline at end of file
-- 
GitLab


From 1395f091128c218e70c197cd698304e208772e1a Mon Sep 17 00:00:00 2001
From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr>
Date: Mon, 28 Feb 2022 11:25:44 +0100
Subject: [PATCH 2/6] Correction : checker date not required -> pas de
 transformation; on garde la chaine vide

---
 src/main/java/fr/inra/oresing/rest/OreSiService.java | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/main/java/fr/inra/oresing/rest/OreSiService.java b/src/main/java/fr/inra/oresing/rest/OreSiService.java
index 76698f058..6dcec3220 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiService.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java
@@ -426,7 +426,9 @@ public class OreSiService {
                         lineCheckers.forEach(lineChecker -> {
                             Set<ValidationCheckResult> validationCheckResults = lineChecker.checkReference(referenceDatumBeforeChecking);
                             if (lineChecker instanceof DateLineChecker) {
-                                validationCheckResults.forEach(validationCheckResult -> {
+                                validationCheckResults.stream()
+                                        .filter(DateValidationCheckResult.class::isInstance)
+                                        .forEach(validationCheckResult -> {
                                     final DateLineChecker dateLineChecker = (DateLineChecker) lineChecker;
                                     final DateValidationCheckResult dateValidationCheckResult = (DateValidationCheckResult) validationCheckResult;
                                     final ReferenceColumnValue referenceColumnValue = referenceDatum.get((ReferenceColumn) dateValidationCheckResult.getTarget());
-- 
GitLab


From ff7bd7e4d8dd782f5b396274527b50eb3c6f33a5 Mon Sep 17 00:00:00 2001
From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr>
Date: Tue, 1 Mar 2022 10:02:35 +0100
Subject: [PATCH 3/6] Correction d'une ligne perdue

---
 src/main/java/fr/inra/oresing/rest/RelationalService.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/fr/inra/oresing/rest/RelationalService.java b/src/main/java/fr/inra/oresing/rest/RelationalService.java
index 7adfa33c7..543bcd7fc 100644
--- a/src/main/java/fr/inra/oresing/rest/RelationalService.java
+++ b/src/main/java/fr/inra/oresing/rest/RelationalService.java
@@ -355,7 +355,7 @@ public class RelationalService implements InitializingBean, DisposableBean {
                     })
                     .collect(Collectors.joining(", ", "(", ")"));
             String quotedReferenceType = quoteSqlIdentifier(referenceType);
-            String castedColumnSelect = columns.stream()
+            String castedColumnSelect = entry.getValue().getColumns().keySet().stream()
                     .map(ReferenceColumn::new)
                     .map(referenceColumn -> {
                         String columnName = quoteSqlIdentifier(referenceColumn.getColumn());
-- 
GitLab


From 3ca7eec01f4510c773df92f2365259822b8a9bae Mon Sep 17 00:00:00 2001
From: Brendan Le Ny <bleny@codelutin.com>
Date: Tue, 1 Mar 2022 11:14:05 +0100
Subject: [PATCH 4/6] =?UTF-8?q?Renforce=20le=20type=20dans=20DateValidatio?=
 =?UTF-8?q?nCheckResult=20pour=20faciliter=20la=20compr=C3=A9hension=20de?=
 =?UTF-8?q?=20la=20transformation=20des=20dates=20pour=20stockage?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../inra/oresing/checker/DateLineChecker.java | 13 +----
 .../fr/inra/oresing/rest/OreSiService.java    | 26 +++++-----
 .../DateValidationCheckResult.java            | 51 +++++--------------
 3 files changed, 26 insertions(+), 64 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/checker/DateLineChecker.java b/src/main/java/fr/inra/oresing/checker/DateLineChecker.java
index 7e1e2b252..c2565d47f 100644
--- a/src/main/java/fr/inra/oresing/checker/DateLineChecker.java
+++ b/src/main/java/fr/inra/oresing/checker/DateLineChecker.java
@@ -10,13 +10,9 @@ import fr.inra.oresing.transformer.LineTransformer;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.time.temporal.TemporalAccessor;
-import java.util.Map;
 
 public class DateLineChecker implements CheckerOnOneVariableComponentLineChecker<DateLineCheckerConfiguration> {
 
-    public static final String PARAM_PATTERN = "pattern";
-    public static final String PARAM_DATE_TIME_FORMATTER = "dateTimeFormatter";
-    public static final String PARAM_DATE = "date";
     public static final String PATTERN_DATE_REGEXP = "^date:.{19}:";
     private final CheckerTarget target;
     private final DateLineCheckerConfiguration configuration;
@@ -52,15 +48,10 @@ public class DateLineChecker implements CheckerOnOneVariableComponentLineChecker
         try {
             value = sortableDateToFormattedDate(value);
             TemporalAccessor date = dateTimeFormatter.parse(value);
-            Map<String, Object> params = ImmutableMap.of(
-                    PARAM_PATTERN, pattern,
-                    PARAM_DATE_TIME_FORMATTER, dateTimeFormatter,
-                    target.getType().name(), target.getTarget(),
-                    PARAM_DATE, date
-            );
-            validationCheckResult = DateValidationCheckResult.success(params);
+            validationCheckResult = DateValidationCheckResult.success(target, date);
         } catch (DateTimeParseException e) {
             validationCheckResult = DateValidationCheckResult.error(
+                    target,
                     getTarget().getInternationalizedKey("invalidDate"), ImmutableMap.of(
                             "target", target.getTarget(),
                             "pattern", pattern,
diff --git a/src/main/java/fr/inra/oresing/rest/OreSiService.java b/src/main/java/fr/inra/oresing/rest/OreSiService.java
index 6a0f8566c..1a1da8567 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiService.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java
@@ -435,19 +435,17 @@ public class OreSiService {
                             Set<ValidationCheckResult> validationCheckResults = lineChecker.checkReference(referenceDatumBeforeChecking);
                             if (lineChecker instanceof DateLineChecker) {
                                 validationCheckResults.stream()
+                                        .filter(ValidationCheckResult::isSuccess)
                                         .filter(DateValidationCheckResult.class::isInstance)
-                                        .forEach(validationCheckResult -> {
-                                    final DateLineChecker dateLineChecker = (DateLineChecker) lineChecker;
-                                    final DateValidationCheckResult dateValidationCheckResult = (DateValidationCheckResult) validationCheckResult;
-                                    final ReferenceColumnValue referenceColumnValue = referenceDatum.get((ReferenceColumn) dateValidationCheckResult.getTarget());
-                                     referenceDatum.put(
-                                             (ReferenceColumn) dateValidationCheckResult.getTarget(),
-                                             referenceDatumBeforeChecking.get((ReferenceColumn) dateValidationCheckResult.getTarget())
-                                                     .transform(v ->
-                                                     String.format("date:%s:%s",dateValidationCheckResult.getMessage(), v)
-                                                     )
-                                     );
-
+                                        .map(DateValidationCheckResult.class::cast)
+                                        .forEach(dateValidationCheckResult -> {
+                                            ReferenceColumn referenceColumn = (ReferenceColumn) dateValidationCheckResult.getTarget().getTarget();
+                                            ReferenceColumnValue referenceColumnRawValue = referenceDatumBeforeChecking.get(referenceColumn);
+                                            ReferenceColumnValue valueToStoreInDatabase = referenceColumnRawValue
+                                                    .transform(rawValue ->
+                                                            String.format("date:%s:%s", dateValidationCheckResult.getLocalDateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), rawValue)
+                                                    );
+                                            referenceDatum.put(referenceColumn, valueToStoreInDatabase);
                                 });
                             } else if (lineChecker instanceof ReferenceLineChecker) {
                                 ReferenceLineChecker referenceLineChecker = (ReferenceLineChecker) lineChecker;
@@ -869,7 +867,7 @@ public class OreSiService {
                 ValidationCheckResult validationCheckResult = lineChecker.check(datum);
                 if (validationCheckResult.isSuccess()) {
                     if (validationCheckResult instanceof DateValidationCheckResult) {
-                        VariableComponentKey variableComponentKey = (VariableComponentKey) ((DateValidationCheckResult) validationCheckResult).getTarget();
+                        VariableComponentKey variableComponentKey = (VariableComponentKey) ((DateValidationCheckResult) validationCheckResult).getTarget().getTarget();
                         dateValidationCheckResultImmutableMap.put(variableComponentKey, (DateValidationCheckResult) validationCheckResult);
                     }
                     if (validationCheckResult instanceof ReferenceValidationCheckResult) {
@@ -922,7 +920,7 @@ public class OreSiService {
                     String component = variableComponentKey.getComponent();
                     String value = entry2.getValue();
                     if (dateValidationCheckResultImmutableMap.containsKey(entry2.getKey())) {
-                        value = String.format("date:%s:%s", dateValidationCheckResultImmutableMap.get(variableComponentKey).getMessage(), value);
+                        value = String.format("date:%s:%s", dateValidationCheckResultImmutableMap.get(variableComponentKey).getLocalDateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), value);
                     }
                     toStore.computeIfAbsent(variable, k -> new LinkedHashMap<>()).put(component, value);
                     refsLinkedToToStore.computeIfAbsent(variable, k -> new LinkedHashMap<>()).put(component, refsLinkedTo.get(variableComponentKey));
diff --git a/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java b/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java
index 4debb3776..93be9d30e 100644
--- a/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java
+++ b/src/main/java/fr/inra/oresing/rest/validationcheckresults/DateValidationCheckResult.java
@@ -3,7 +3,6 @@ package fr.inra.oresing.rest.validationcheckresults;
 import com.google.common.collect.ImmutableMap;
 import fr.inra.oresing.ValidationLevel;
 import fr.inra.oresing.checker.CheckerTarget;
-import fr.inra.oresing.checker.DateLineChecker;
 import fr.inra.oresing.rest.ValidationCheckResult;
 import lombok.Value;
 
@@ -14,52 +13,26 @@ import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalQueries;
 import java.util.Map;
-import java.util.Optional;
 
 @Value
 public class DateValidationCheckResult implements ValidationCheckResult {
     ValidationLevel level;
     String message;
     Map<String, Object> messageParams;
-    Object target;
+    CheckerTarget target;
     TemporalAccessor date;
-
-    public DateValidationCheckResult(ValidationLevel level, String message, Map<String, Object> messageParams, Object target, TemporalAccessor date) {
-        this.level = level;
-        this.message = message;
-        this.messageParams = messageParams;
-        this.target = target;
-        this.date = date;
-    }
-
-    public DateValidationCheckResult(ValidationLevel success, Map<String, Object> params) {
-        this.messageParams = params;
-        this.level = success;
-        this.target = Optional.ofNullable(messageParams)
-                .map(mp->mp.getOrDefault(
-                        CheckerTarget.CheckerTargetType.PARAM_COLUMN.name(),
-                        mp.getOrDefault(CheckerTarget.CheckerTargetType.PARAM_VARIABLE_COMPONENT_KEY.name(), null)
-                ))
-                .orElse(null);
-        this.date = (TemporalAccessor) Optional.ofNullable(messageParams).map(mp->mp.getOrDefault(DateLineChecker.PARAM_DATE, null)).orElse(null);
-        LocalDateTime localDateTime = null;
-        if(date!=null){
-            LocalDate localdate = date.query(TemporalQueries.localDate());
-            localdate=localdate==null?LocalDate.of(1970, 1, 1):localdate;
-            LocalTime localTime = date.query(TemporalQueries.localTime());
-            localTime=localTime==null?LocalTime.MIN:localTime;
-            localDateTime = localdate.atTime(localTime);
-        }
-
-
-        this.message = localDateTime==null?null:localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
-    }
-
-    public static DateValidationCheckResult success(Map<String, Object> params) {
-        return new DateValidationCheckResult(ValidationLevel.SUCCESS, params);
+    LocalDateTime localDateTime;
+
+    public static DateValidationCheckResult success(CheckerTarget target, TemporalAccessor date) {
+        LocalDate localdate = date.query(TemporalQueries.localDate());
+        localdate = localdate == null ? LocalDate.of(1970, 1, 1) : localdate;
+        LocalTime localTime = date.query(TemporalQueries.localTime());
+        localTime = localTime == null ? LocalTime.MIN : localTime;
+        LocalDateTime localDateTime = localdate.atTime(localTime);
+        return new DateValidationCheckResult(ValidationLevel.SUCCESS, null, null, target, date, localDateTime);
     }
 
-    public static DateValidationCheckResult error(String message, ImmutableMap<String, Object> messageParams) {
-        return new DateValidationCheckResult(ValidationLevel.ERROR, message, messageParams, null, null);
+    public static DateValidationCheckResult error(CheckerTarget target, String message, ImmutableMap<String, Object> messageParams) {
+        return new DateValidationCheckResult(ValidationLevel.ERROR, message, messageParams, target, null, null);
     }
 }
\ No newline at end of file
-- 
GitLab


From 3e99158931afc98dd00d5915bf61b4eae49cd035 Mon Sep 17 00:00:00 2001
From: Brendan Le Ny <bleny@codelutin.com>
Date: Tue, 1 Mar 2022 11:21:16 +0100
Subject: [PATCH 5/6] Supprime du code mort

---
 src/main/java/fr/inra/oresing/rest/RelationalService.java | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/main/java/fr/inra/oresing/rest/RelationalService.java b/src/main/java/fr/inra/oresing/rest/RelationalService.java
index 543bcd7fc..651813385 100644
--- a/src/main/java/fr/inra/oresing/rest/RelationalService.java
+++ b/src/main/java/fr/inra/oresing/rest/RelationalService.java
@@ -349,7 +349,6 @@ public class RelationalService implements InitializingBean, DisposableBean {
             String columnsAsSchema = allReferenceColumnsPerMultiplicity.values().stream()
                     .map(referenceColumn -> {
                         String columnName = quoteSqlIdentifier(referenceColumn.getColumn());
-                        SqlPrimitiveType columnType = sqlTypePerColumns.getOrDefault(referenceColumn, SqlPrimitiveType.TEXT);
                         String columnDeclaration = String.format("%s %s", columnName, SqlPrimitiveType.TEXT);
                         return columnDeclaration;
                     })
-- 
GitLab


From cafdc7716515b657faf346fd94b890c31429a07a Mon Sep 17 00:00:00 2001
From: Brendan Le Ny <bleny@codelutin.com>
Date: Tue, 1 Mar 2022 11:22:05 +0100
Subject: [PATCH 6/6] =?UTF-8?q?Dans=20les=20vue=20relationnelles,=20int?=
 =?UTF-8?q?=C3=A8gre=20aussi=20les=20colonnes=20non-d=C3=A9clar=C3=A9es?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/java/fr/inra/oresing/rest/RelationalService.java | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/rest/RelationalService.java b/src/main/java/fr/inra/oresing/rest/RelationalService.java
index 651813385..09a39eb3d 100644
--- a/src/main/java/fr/inra/oresing/rest/RelationalService.java
+++ b/src/main/java/fr/inra/oresing/rest/RelationalService.java
@@ -354,8 +354,7 @@ public class RelationalService implements InitializingBean, DisposableBean {
                     })
                     .collect(Collectors.joining(", ", "(", ")"));
             String quotedReferenceType = quoteSqlIdentifier(referenceType);
-            String castedColumnSelect = entry.getValue().getColumns().keySet().stream()
-                    .map(ReferenceColumn::new)
+            String castedColumnSelect = allReferenceColumnsPerMultiplicity.values().stream()
                     .map(referenceColumn -> {
                         String columnName = quoteSqlIdentifier(referenceColumn.getColumn());
                         SqlPrimitiveType columnType = sqlTypePerColumns.getOrDefault(referenceColumn, SqlPrimitiveType.TEXT);
-- 
GitLab