From fdecbcf216453e4fa75ca411a354ab4bfe208605 Mon Sep 17 00:00:00 2001
From: Brendan Le Ny <bleny@codelutin.com>
Date: Fri, 18 Feb 2022 12:00:22 +0100
Subject: [PATCH] =?UTF-8?q?Ajoute=20un=20contr=C3=B4le=20de=20validation?=
 =?UTF-8?q?=20qui=20emp=C3=AAche=20de=20ne=20pas=20indiquer=20de=20composa?=
 =?UTF-8?q?nt=20pour=20la=20cl=C3=A9=20naturelle=20d'un=20r=C3=A9f=C3=A9re?=
 =?UTF-8?q?ntiel?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../rest/ApplicationConfigurationService.java | 18 +++++++++-------
 .../rest/ConfigurationParsingResult.java      |  6 ++++++
 .../fr/inra/oresing/rest/OreSiService.java    | 21 +++++++------------
 .../ApplicationConfigurationServiceTest.java  | 10 +++++++++
 ui2/src/locales/en.json                       |  1 +
 ui2/src/locales/fr.json                       |  1 +
 6 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/rest/ApplicationConfigurationService.java b/src/main/java/fr/inra/oresing/rest/ApplicationConfigurationService.java
index 6d02b79f0..98b3a1a15 100644
--- a/src/main/java/fr/inra/oresing/rest/ApplicationConfigurationService.java
+++ b/src/main/java/fr/inra/oresing/rest/ApplicationConfigurationService.java
@@ -168,7 +168,7 @@ public class ApplicationConfigurationService {
         }
 
         for (Map.Entry<String, Configuration.ReferenceDescription> referenceEntry : configuration.getReferences().entrySet()) {
-            verifyReferenceKeyColumnsExists(configuration, builder, referenceEntry);
+            verifyReferenceKeyColumns(configuration, builder, referenceEntry);
             verifyInternationalizedColumnsExists(configuration, builder, referenceEntry);
             verifyInternationalizedColumnsExistsForPattern(configuration, builder, referenceEntry);
             verifyValidationCheckersAreValids(configuration, builder, referenceEntry, references);
@@ -470,15 +470,19 @@ public class ApplicationConfigurationService {
         }
     }
 
-    private void verifyReferenceKeyColumnsExists(Configuration configuration, ConfigurationParsingResult.Builder builder, Map.Entry<String, Configuration.ReferenceDescription> referenceEntry) {
+    private void verifyReferenceKeyColumns(Configuration configuration, ConfigurationParsingResult.Builder builder, Map.Entry<String, Configuration.ReferenceDescription> referenceEntry) {
         String reference = referenceEntry.getKey();
         Configuration.ReferenceDescription referenceDescription = referenceEntry.getValue();
         List<String> keyColumns = referenceDescription.getKeyColumns();
-        Set<String> columns = referenceDescription.getColumns().keySet();
-        ImmutableSet<String> keyColumnsSet = ImmutableSet.copyOf(keyColumns);
-        ImmutableSet<String> unknownUsedAsKeyElementColumns = Sets.difference(keyColumnsSet, columns).immutableCopy();
-        if (!unknownUsedAsKeyElementColumns.isEmpty()) {
-            builder.recordInvalidKeyColumns(reference, unknownUsedAsKeyElementColumns, columns);
+        if (keyColumns.isEmpty()) {
+            builder.recordMissingKeyColumnsForReference(reference);
+        } else {
+            Set<String> columns = referenceDescription.getColumns().keySet();
+            ImmutableSet<String> keyColumnsSet = ImmutableSet.copyOf(keyColumns);
+            ImmutableSet<String> unknownUsedAsKeyElementColumns = Sets.difference(keyColumnsSet, columns).immutableCopy();
+            if (!unknownUsedAsKeyElementColumns.isEmpty()) {
+                builder.recordInvalidKeyColumns(reference, unknownUsedAsKeyElementColumns, columns);
+            }
         }
     }
 
diff --git a/src/main/java/fr/inra/oresing/rest/ConfigurationParsingResult.java b/src/main/java/fr/inra/oresing/rest/ConfigurationParsingResult.java
index b75f8d5f7..6c6cea221 100644
--- a/src/main/java/fr/inra/oresing/rest/ConfigurationParsingResult.java
+++ b/src/main/java/fr/inra/oresing/rest/ConfigurationParsingResult.java
@@ -363,5 +363,11 @@ public class ConfigurationParsingResult {
                     "references", references)
             );
         }
+
+        public Builder recordMissingKeyColumnsForReference(String reference) {
+            return recordError("missingKeyColumnsForReference", ImmutableMap.of(
+                    "reference", reference)
+            );
+        }
     }
 }
\ 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 e58048116..54826d2f6 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiService.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java
@@ -468,19 +468,14 @@ public class OreSiService {
                             }
                         });
                         ReferenceValue e = new ReferenceValue();
-                        Ltree naturalKey;
-                        if (ref.getKeyColumns().isEmpty()) {
-                            UUID technicalId = e.getId();
-                            naturalKey = Ltree.fromUuid(technicalId);
-                        } else {
-                            String naturalKeyAsString = ref.getKeyColumns().stream()
-                                    .map(ReferenceColumn::new)
-                                    .map(referenceDatum::get)
-                                    .filter(StringUtils::isNotEmpty)
-                                    .map(Ltree::escapeToLabel)
-                                    .collect(Collectors.joining(KEYCOLUMN_SEPARATOR));
-                            naturalKey = Ltree.fromSql(naturalKeyAsString);
-                        }
+                        Preconditions.checkState(!ref.getColumns().isEmpty(), "aucune colonne désignée comme clé naturelle pour le référentiel " + refType);
+                        String naturalKeyAsString = ref.getKeyColumns().stream()
+                                .map(ReferenceColumn::new)
+                                .map(referenceDatum::get)
+                                .filter(StringUtils::isNotEmpty)
+                                .map(Ltree::escapeToLabel)
+                                .collect(Collectors.joining(KEYCOLUMN_SEPARATOR));
+                        Ltree naturalKey = Ltree.fromSql(naturalKeyAsString);
                         Ltree recursiveNaturalKey = naturalKey;
                         final Ltree refTypeAsLabel = Ltree.fromUnescapedString(refType);
                         if (isRecursive) {
diff --git a/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java b/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
index 98d342c0c..14184cf62 100644
--- a/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
+++ b/src/test/java/fr/inra/oresing/rest/ApplicationConfigurationServiceTest.java
@@ -458,4 +458,14 @@ public class ApplicationConfigurationServiceTest {
         Assert.assertTrue(((Set)onlyError.getMessageParams().get("unknownUsedAsInternationalizedColumns")).contains("nom du site"));
         Assert.assertTrue(((Set)onlyError.getMessageParams().get("knownColumns")).contains("nom du site_fr"));
     }
+
+    @Test
+    public void testMissingKeyColumnsForReference() {
+        ConfigurationParsingResult configurationParsingResult = parseYaml("keyColumns: [nom du projet_key]", "");
+        Assert.assertFalse(configurationParsingResult.isValid());
+        ValidationCheckResult onlyError = Iterables.getOnlyElement(configurationParsingResult.getValidationCheckResults());
+        log.debug(onlyError.getMessage());
+        Assert.assertEquals("missingKeyColumnsForReference", onlyError.getMessage());
+        Assert.assertEquals("projets", onlyError.getMessageParams().get("reference"));
+    }
 }
\ No newline at end of file
diff --git a/ui2/src/locales/en.json b/ui2/src/locales/en.json
index 54ea173b4..07220ac68 100644
--- a/ui2/src/locales/en.json
+++ b/ui2/src/locales/en.json
@@ -120,6 +120,7 @@
         "missingParamColumnReferenceForCheckerInReference":"In the description of the <code> {reference} </code>, the validation rule <code> {validationRuleDescriptionEntryKey} </code> does not specify on which columns the rule should be executed by declaring a <code> columns </code> parameter ",
         "csvBoundToUnknownVariableComponent":"In the CSV format, header <code>{header}</code> is bound to <code>{variable}</code> but it has no <code>{component}</code> component. Known components: <code>{components}</code>",
         "invalidKeyColumns":"In the description of reference <code>{reference}</code>, colomns <code>{unknownUsedAsKeyElementColumns}</code> are declared as components of the key but there are no such columns. Known columns are <code>{knownColumns}</code>",
+        "missingKeyColumnsForReference": "In the description of reference <code>{reference}</code>, you must declare the components (at least one) of the key",
         "invalidInternationalizedColumns":"In the repository description <code> {reference} </code>, the columns <code> {unknownUsedAsInternationalizedColumns} </code> are declared as part of internationalizable columns when they do not exist. Known columns: <code> {knownColumns} </code> ",
         "invalidInternationalizedColumnsForDataType": "In the <code> {reference} </code> repository overload of the <code> {dataType} </code> data type description, the <code> {unknownUsedAsInternationalizedColumns} </code> columns are declared as part of internationalizable columns when they do not exist. Known columns: <code> {knownColumns} </code> ",
         "unknownReferenceInDatatypeReferenceDisplay": "In the repository display overload of the <code> {dataType} </code> datatype description, the <code> {reference} </code> repository is unknown. Known repositories known : <code> {references} </code> ",
diff --git a/ui2/src/locales/fr.json b/ui2/src/locales/fr.json
index e82d10e87..4ba7c9494 100644
--- a/ui2/src/locales/fr.json
+++ b/ui2/src/locales/fr.json
@@ -121,6 +121,7 @@
         "missingParamColumnReferenceForCheckerInReference": "Dans la description de la <code>{reference}</code>, la règle de validation <code>{validationRuleDescriptionEntryKey}</code> ne précise pas sur quelles colonnes la règle doit s'exécuter en déclarant un paramètre <code>columns</code>",
         "csvBoundToUnknownVariableComponent": "Dans le format CSV, l’entête <code>{header}</code> est lié à la variable <code>{variable}</code> mais elle n’a pas de composant <code>{component}</code>. Composants connus <code>{components}</code>",
         "invalidKeyColumns": "Dans la description du référentiel <code>{reference}</code>, les colonnes <code>{unknownUsedAsKeyElementColumns}</code> sont déclarées comme faisant partie de la clé alors qu’elles n’existent pas. Colonnes connues : <code>{knownColumns}</code>",
+        "missingKeyColumnsForReference": "Dans la description du référentiel <code>{reference}</code>, vous devez déclarer les colonnes (au moins une) qui composent la clé naturelle",
         "invalidInternationalizedColumns": "Dans la description du référentiel <code>{reference}</code>, les colonnes <code>{unknownUsedAsInternationalizedColumns}</code> sont déclarées comme faisant partie de colonnes internationalisables alors qu’elles n’existent pas. Colonnes connues : <code>{knownColumns}</code>",
         "invalidInternationalizedColumnsForDataType": "Dans la surcharge du référentiel <code>{reference}</code> de la description du type de donnée <code>{dataType}</code>, les colonnes <code>{unknownUsedAsInternationalizedColumns}</code> sont déclarées comme faisant partie de colonnes internationalisables alors qu’elles n’existent pas. Colonnes connues : <code>{knownColumns}</code>",
         "unknownReferenceInDatatypeReferenceDisplay": "Dans la surcharge de l'affichage des référentiels de la description du type de donnée <code>{dataType}</code>, le référentiel <code>{reference}</code> est inconnu . Référentiels connus connues : <code>{references}</code>",
-- 
GitLab