From 5963b92ec4788ca82f1db9602a3060c71490d5bc Mon Sep 17 00:00:00 2001 From: Brendan Le Ny <bleny@codelutin.com> Date: Tue, 15 Mar 2022 16:24:00 +0100 Subject: [PATCH 1/3] =?UTF-8?q?Envoie=20au=20frontend=20des=20collections?= =?UTF-8?q?=20si=20un=20r=C3=A9f=C3=A9rentiel=20=C3=A0=20une=20colonne=20m?= =?UTF-8?q?ulti-valu=C3=A9e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inra/oresing/checker/CheckerFactory.java | 1 - .../model/ReferenceColumnIndexedValue.java | 11 ++++++---- .../model/ReferenceColumnMultipleValue.java | 12 ++++------- .../model/ReferenceColumnSingleValue.java | 4 ++-- .../oresing/model/ReferenceColumnValue.java | 20 +++++++++++++++---- .../fr/inra/oresing/model/ReferenceDatum.java | 8 ++++---- .../persistence/ReferenceValueRepository.java | 2 +- .../inra/oresing/rest/ApplicationResult.java | 2 +- .../inra/oresing/rest/GetReferenceResult.java | 2 +- 9 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/main/java/fr/inra/oresing/checker/CheckerFactory.java b/src/main/java/fr/inra/oresing/checker/CheckerFactory.java index 1084dfb51..a82c5ae36 100644 --- a/src/main/java/fr/inra/oresing/checker/CheckerFactory.java +++ b/src/main/java/fr/inra/oresing/checker/CheckerFactory.java @@ -9,7 +9,6 @@ import fr.inra.oresing.model.Application; import fr.inra.oresing.model.Configuration; import fr.inra.oresing.model.ReferenceColumn; import fr.inra.oresing.model.VariableComponentKey; -import fr.inra.oresing.model.internationalization.InternationalizationDisplay; import fr.inra.oresing.persistence.DataRepository; import fr.inra.oresing.persistence.Ltree; import fr.inra.oresing.persistence.OreSiRepository; diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java index 04ad1f729..4620969bd 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java @@ -1,6 +1,5 @@ package fr.inra.oresing.model; -import com.google.common.base.Joiner; import com.google.common.collect.Maps; import fr.inra.oresing.persistence.Ltree; import lombok.Value; @@ -11,7 +10,7 @@ import java.util.function.Function; import java.util.stream.Collectors; @Value -public class ReferenceColumnIndexedValue implements ReferenceColumnValue<Map<String, String>> { +public class ReferenceColumnIndexedValue implements ReferenceColumnValue<Map<String, String>, Map<String, String>> { Map<Ltree, String> values; @@ -27,12 +26,16 @@ public class ReferenceColumnIndexedValue implements ReferenceColumnValue<Map<Str } @Override - public String toJsonForFrontend() { - return Joiner.on(",").withKeyValueSeparator("=").join(toJsonForDatabase()); + public Map<String, String> toJsonForFrontend() { + return toStringStringMap(); } @Override public Map<String, String> toJsonForDatabase() { + return toStringStringMap(); + } + + private Map<String, String> toStringStringMap() { Map<String, String> jsonForDatabase = values.entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().getSql(), Map.Entry::getValue)); return jsonForDatabase; diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java index cb6e7e87e..9c4efc0a8 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java @@ -1,6 +1,5 @@ package fr.inra.oresing.model; -import com.google.common.base.Preconditions; import lombok.Value; import java.util.Set; @@ -11,7 +10,7 @@ import java.util.stream.Collectors; * Permet de stocker la valeur pour une colonne d'un référentiel lorsque cette colonne est multi-valuées ({@link fr.inra.oresing.checker.Multiplicity#MANY}). */ @Value -public class ReferenceColumnMultipleValue implements ReferenceColumnValue<Set<String>> { +public class ReferenceColumnMultipleValue implements ReferenceColumnValue<Set<String>, Set<String>> { private static final String COLLECTION_AS_JSON_STRING_SEPARATOR = ","; @@ -28,16 +27,13 @@ public class ReferenceColumnMultipleValue implements ReferenceColumnValue<Set<St } @Override - public ReferenceColumnValue<Set<String>> transform(Function<String, String> transformation) { + public ReferenceColumnMultipleValue transform(Function<String, String> transformation) { Set<String> transformedValues = values.stream().map(transformation).collect(Collectors.toSet()); return new ReferenceColumnMultipleValue(transformedValues); } @Override - public String toJsonForFrontend() { - String jsonContent = values.stream() - .peek(value -> Preconditions.checkState(value.contains(COLLECTION_AS_JSON_STRING_SEPARATOR), value + " contient " + COLLECTION_AS_JSON_STRING_SEPARATOR)) - .collect(Collectors.joining(COLLECTION_AS_JSON_STRING_SEPARATOR)); - return jsonContent; + public Set<String> toJsonForFrontend() { + return values; } } diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java index 5b50bfbc4..53ff8b8d8 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java @@ -9,7 +9,7 @@ import java.util.function.Function; * Permet de stocker la valeur pour une colonne d'un référentiel lorsque cette colonne a une seule valeur associée ({@link fr.inra.oresing.checker.Multiplicity#ONE}). */ @Value -public class ReferenceColumnSingleValue implements ReferenceColumnValue<String> { +public class ReferenceColumnSingleValue implements ReferenceColumnValue<String, String> { private static final ReferenceColumnSingleValue EMPTY = new ReferenceColumnSingleValue(""); @@ -33,7 +33,7 @@ public class ReferenceColumnSingleValue implements ReferenceColumnValue<String> } @Override - public ReferenceColumnValue<String> transform(Function<String, String> transformation) { + public ReferenceColumnSingleValue transform(Function<String, String> transformation) { String transformedValue = transformation.apply(value); return new ReferenceColumnSingleValue(transformedValue); } diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java index 2ea25c8b4..8a97cf345 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java @@ -3,12 +3,24 @@ package fr.inra.oresing.model; import java.util.Collection; import java.util.function.Function; -public interface ReferenceColumnValue<T> extends SomethingToBeStoredAsJsonInDatabase<T>, SomethingToBeSentToFrontend<String> { +/** + * Représente la valeur pour une colonne donnée d'une ligne d'un référentiel donné. + * + * Voir les sous-classes qui gère chacune une forme de multiplicité. + * + * @param <T> le type dans lequel ça va être transformé pour être stocké sous forme de JSON en base + * @param <F> le type dans lequel ça va être transformé pour être envoyé au frontend sous forme de JSON + */ +public interface ReferenceColumnValue<T, F> extends SomethingToBeStoredAsJsonInDatabase<T>, SomethingToBeSentToFrontend<F> { + /** + * L'ensemble des valeurs pour lesquelles il faut appliquer les checkers + */ Collection<String> getValuesToCheck(); - ReferenceColumnValue<T> transform(Function<String, String> transformation); + /** + * Une copie de l'objet mais après avoir appliqué une transformation sur toutes les valeurs contenues. + */ + ReferenceColumnValue<T, F> transform(Function<String, String> transformation); - @Override - String toJsonForFrontend(); } diff --git a/src/main/java/fr/inra/oresing/model/ReferenceDatum.java b/src/main/java/fr/inra/oresing/model/ReferenceDatum.java index f32eb134e..8ddfc1984 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceDatum.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceDatum.java @@ -12,7 +12,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -public class ReferenceDatum implements SomethingThatCanProvideEvaluationContext, SomethingToBeStoredAsJsonInDatabase<Map<String, Object>>, SomethingToBeSentToFrontend<Map<String, String>> { +public class ReferenceDatum implements SomethingThatCanProvideEvaluationContext, SomethingToBeStoredAsJsonInDatabase<Map<String, Object>>, SomethingToBeSentToFrontend<Map<String, Object>> { private final Map<ReferenceColumn, ReferenceColumnValue> values; @@ -108,10 +108,10 @@ public class ReferenceDatum implements SomethingThatCanProvideEvaluationContext, } @Override - public Map<String, String> toJsonForFrontend() { - Map<String, String> map = new LinkedHashMap<>(); + public Map<String, Object> toJsonForFrontend() { + Map<String, Object> map = new LinkedHashMap<>(); for (Map.Entry<ReferenceColumn, ReferenceColumnValue> entry : values.entrySet()) { - String valueThatMayBeNull = Optional.ofNullable(entry.getValue()) + Object valueThatMayBeNull = Optional.ofNullable(entry.getValue()) .map(ReferenceColumnValue::toJsonForFrontend) .orElse(null); map.put(entry.getKey().toJsonForDatabase(), valueThatMayBeNull); diff --git a/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java b/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java index 982c937bf..9a21a60ab 100644 --- a/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java +++ b/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java @@ -133,7 +133,7 @@ public class ReferenceValueRepository extends JsonTableInApplicationSchemaReposi } else { display = null; } - Map<String, String> values = referenceDatum.toJsonForFrontend(); + Map<String, Object> values = referenceDatum.toJsonForFrontend(); return new ApplicationResult.Reference.ReferenceUUIDAndDisplay(display, result.getId(), values); }; return findAllByReferenceType(referenceType).stream() diff --git a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java index c792940ab..06c89b991 100644 --- a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java +++ b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java @@ -36,7 +36,7 @@ public class ApplicationResult { public static class ReferenceUUIDAndDisplay { String display; UUID uuid; - Map<String, String> values; + Map<String, Object> values; } } diff --git a/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java index e7aa4f5e5..2618763e7 100644 --- a/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java +++ b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java @@ -14,6 +14,6 @@ public class GetReferenceResult { String hierarchicalKey; String hierarchicalReference; String naturalKey; - Map<String, String> values; + Map<String, Object> values; } } \ No newline at end of file -- GitLab From c433a4b91f01c02ee28717d59d023469f3e383a1 Mon Sep 17 00:00:00 2001 From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr> Date: Mon, 21 Mar 2022 17:24:41 +0100 Subject: [PATCH 2/3] Essai de correction des display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -sortie des calculs à résultat constant dans une constante - requête d'extraction des displays - modification pour remplacer les naturalkey du pattern par leur display --- .../model/ReferenceColumnDisplayValue.java | 98 ++++++++ .../model/ReferenceColumnIndexedValue.java | 10 +- .../model/ReferenceColumnMultipleValue.java | 10 +- .../model/ReferenceColumnSingleValue.java | 8 +- .../oresing/model/ReferenceColumnValue.java | 5 +- .../InternationalizationDisplay.java | 8 +- .../persistence/ReferenceValueRepository.java | 33 +++ .../fr/inra/oresing/rest/OreSiService.java | 101 +++------ .../inra/oresing/rest/ReferenceImporter.java | 21 +- .../rest/ReferenceImporterContext.java | 211 ++++++++++++------ src/test/resources/data/acbb/acbb.yaml | 12 + 11 files changed, 356 insertions(+), 161 deletions(-) create mode 100644 src/main/java/fr/inra/oresing/model/ReferenceColumnDisplayValue.java diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnDisplayValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnDisplayValue.java new file mode 100644 index 000000000..5bfee2f74 --- /dev/null +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnDisplayValue.java @@ -0,0 +1,98 @@ +package fr.inra.oresing.model; + +import fr.inra.oresing.rest.ReferenceImporterContext; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.Value; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +/** + * Permet de stocker la valeur pour une colonne d'un référentiel lorsque cette colonne a une seule valeur associée ({@link fr.inra.oresing.checker.Multiplicity#ONE}). + */ +@Value +public class ReferenceColumnDisplayValue implements ReferenceColumnValue<String, ReferenceColumnDisplayValue.ReferenceColumnDisplayValueForLocale> { + + private static final ReferenceColumnDisplayValue EMPTY = new ReferenceColumnDisplayValue(); + + ReferenceColumnDisplayValueForLocale value = null; + + public ReferenceColumnDisplayValue() { + } + + /** + * Un {@link ReferenceColumnDisplayValue} vide (valeur non renseignée ?) + */ + public static ReferenceColumnDisplayValue empty() { + return EMPTY; + } + + @Override + public Collection<String> getValuesToCheck() { + return null; + } + + @Override + public ReferenceColumnValue<String, ReferenceColumnDisplayValueForLocale> transform(Function<String, String> transformation) { + return null; + } + + @Override + public String toValueString(ReferenceImporterContext referenceImporterContext, String referencedColumn, String key) { + return null; + } + + @Override + public ReferenceColumnDisplayValueForLocale toJsonForFrontend() { + return null; + } + + @Override + public String toJsonForDatabase() { + return null; + } + + + @Getter + @Setter + @ToString + public static class ReferenceColumnDisplayValueForLocale { + private String pattern; + private String toStringValue; + private Map<String, String> types; + private Map<String, ReferenceColumnDisplayToReplaceValue> values; + } + + @Getter + @Setter + @ToString + public abstract static class ReferenceColumnDisplayToReplaceValue<T> { + T value; + } + + @Getter + @Setter + @ToString + public static class ReferenceColumnDisplayToReplaceSingleValue extends ReferenceColumnDisplayToReplaceValue<String> { + + } + + @Getter + @Setter + @ToString + public static class ReferenceColumnDisplayToReplaceArrayValue extends ReferenceColumnDisplayToReplaceValue<List<String>> { + + } + + @Getter + @Setter + @ToString + public static class ReferenceColumnDisplayToReplaceMapValue extends ReferenceColumnDisplayToReplaceValue<Map<String, String>> { + + } + +} \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java index 4620969bd..765c69ffe 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnIndexedValue.java @@ -2,6 +2,7 @@ package fr.inra.oresing.model; import com.google.common.collect.Maps; import fr.inra.oresing.persistence.Ltree; +import fr.inra.oresing.rest.ReferenceImporterContext; import lombok.Value; import java.util.Collection; @@ -25,6 +26,13 @@ public class ReferenceColumnIndexedValue implements ReferenceColumnValue<Map<Str return new ReferenceColumnIndexedValue(transformedValues); } + @Override + public String toValueString(ReferenceImporterContext referenceImporterContext, String referencedColumn, String locale) { + return values.entrySet().stream() + .map(ltreeStringEntry -> String.format("\"%s\"\"=%s\"", referenceImporterContext.getDisplayByReferenceAndNaturalKey( referencedColumn,ltreeStringEntry.getKey().toString(), locale), ltreeStringEntry.getValue())) + .collect(Collectors.joining(",","[","]")); + } + @Override public Map<String, String> toJsonForFrontend() { return toStringStringMap(); @@ -40,4 +48,4 @@ public class ReferenceColumnIndexedValue implements ReferenceColumnValue<Map<Str .collect(Collectors.toMap(entry -> entry.getKey().getSql(), Map.Entry::getValue)); return jsonForDatabase; } -} +} \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java index 9c4efc0a8..1334c4899 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnMultipleValue.java @@ -1,5 +1,6 @@ package fr.inra.oresing.model; +import fr.inra.oresing.rest.ReferenceImporterContext; import lombok.Value; import java.util.Set; @@ -32,8 +33,15 @@ public class ReferenceColumnMultipleValue implements ReferenceColumnValue<Set<St return new ReferenceColumnMultipleValue(transformedValues); } + @Override + public String toValueString(ReferenceImporterContext referenceImporterContext, String referencedColumn, String locale) { + return values.stream() + .map(s->referenceImporterContext.getDisplayByReferenceAndNaturalKey(referencedColumn, s, locale)) + .collect(Collectors.joining(",","[","]")); + } + @Override public Set<String> toJsonForFrontend() { return values; } -} +} \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java index 53ff8b8d8..4e8166ff8 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnSingleValue.java @@ -1,5 +1,6 @@ package fr.inra.oresing.model; +import fr.inra.oresing.rest.ReferenceImporterContext; import lombok.Value; import java.util.Set; @@ -38,8 +39,13 @@ public class ReferenceColumnSingleValue implements ReferenceColumnValue<String, return new ReferenceColumnSingleValue(transformedValue); } + @Override + public String toValueString(ReferenceImporterContext referenceImporterContext, String referencedColumn, String locale) { + return referenceImporterContext.getDisplayByReferenceAndNaturalKey(referencedColumn, value, locale); + } + @Override public String toJsonForFrontend() { return value; } -} +} \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java b/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java index 8a97cf345..ea10fcbd0 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceColumnValue.java @@ -1,5 +1,7 @@ package fr.inra.oresing.model; +import fr.inra.oresing.rest.ReferenceImporterContext; + import java.util.Collection; import java.util.function.Function; @@ -23,4 +25,5 @@ public interface ReferenceColumnValue<T, F> extends SomethingToBeStoredAsJsonInD */ ReferenceColumnValue<T, F> transform(Function<String, String> transformation); -} + String toValueString(ReferenceImporterContext referenceImporterContext, String referencedColumn, String key); +} \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationDisplay.java b/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationDisplay.java index 9ce92c431..5ecf041b3 100644 --- a/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationDisplay.java +++ b/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationDisplay.java @@ -3,6 +3,7 @@ package fr.inra.oresing.model.internationalization; import fr.inra.oresing.model.ReferenceColumn; import fr.inra.oresing.model.ReferenceColumnSingleValue; import fr.inra.oresing.model.ReferenceDatum; +import fr.inra.oresing.rest.ReferenceImporterContext; import lombok.Getter; import lombok.Setter; import org.assertj.core.util.Strings; @@ -18,7 +19,10 @@ import java.util.stream.Stream; public class InternationalizationDisplay { Map<String, String> pattern; - public static ReferenceDatum getDisplays(Optional<Map<String, String>> displayPattern, Map<String, Internationalization> displayColumns, ReferenceDatum refValues) { + public static ReferenceDatum getDisplays(ReferenceImporterContext referenceImporterContext, ReferenceDatum refValues) { + Optional<Map<String, String>> displayPattern =referenceImporterContext.getDisplayPattern(); + Map<String, Internationalization> displayColumns = referenceImporterContext.getDisplayColumns(); + String refType = referenceImporterContext.getRefType(); ReferenceDatum displays = new ReferenceDatum(); displayPattern .ifPresent(patterns -> { @@ -33,7 +37,7 @@ public class InternationalizationDisplay { if (displayColumns.containsKey(referencedColumn)) { referencedColumn = displayColumns.get(referencedColumn).getOrDefault(stringEntry.getKey(), referencedColumn); } - internationalizedPattern += refValues.get(new ReferenceColumn(referencedColumn)); + internationalizedPattern += refValues.get(new ReferenceColumn(referencedColumn)).toValueString(referenceImporterContext, referencedColumn, stringEntry.getKey()); } return internationalizedPattern; } diff --git a/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java b/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java index 9a21a60ab..0b83b9bed 100644 --- a/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java +++ b/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java @@ -17,6 +17,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -104,6 +105,38 @@ public class ReferenceValueRepository extends JsonTableInApplicationSchemaReposi return (List<ReferenceValue>) result; } + public Map<String, Map<String, String>> findDisplayByNaturalKey(String refType) { + String query = "select 'java.util.Map' as \"@class\" , jsonb_build_object(naturalkey, jsonb_agg(display)) json\n" + + " from " + getTable().getSqlIdentifier() + ",\n" + + "lateral\n" + + "(select jsonb_build_object(\n" + + " trim('\"__display_' from\n" + + " jsonb_path_query(refvalues, '$.keyvalue()?(@.key like_regex \"__display.*\").key')::text),\n" + + " trim('\"' FROM jsonb_path_query(refvalues, '$.keyvalue()?(@.key like_regex \"__display.*\").value')::text)\n" + + " ) as display\n" + + " )displays\n" + + "where referencetype = :refType\n" + + "group by naturalkey"; + Map<String, Map<String, String>> displayForNaturalKey = new HashMap<>(); + List result = getNamedParameterJdbcTemplate().query(query, new MapSqlParameterSource("refType", refType), getJsonRowMapper()); + for (Object o : result) { + final Map<String, List<Map<String, String>>> o1 = (Map<String, List<Map<String, String>>>) o; + final Map<String, Map<String, String>> collect = o1.entrySet() + .stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> { + Map<String, String> displayMap = new HashMap<>(); + for (Map<String, String> s : e.getValue()) { + displayMap.putAll(s); + } + return displayMap; + } + )); + displayForNaturalKey.putAll(collect); + } + return displayForNaturalKey; + } + public List<List<String>> findReferenceValue(String refType, String column) { AtomicInteger ai = new AtomicInteger(0); String select = Stream.of(column.split(",")) diff --git a/src/main/java/fr/inra/oresing/rest/OreSiService.java b/src/main/java/fr/inra/oresing/rest/OreSiService.java index 4b8745d43..845e2dc27 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiService.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java @@ -4,62 +4,16 @@ import com.google.common.base.Charsets; import com.google.common.base.MoreObjects; 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.Iterators; -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.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.ColumnPresenceConstraint; -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.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.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.model.*; +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; @@ -95,19 +49,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.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.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Matcher; @@ -444,15 +386,36 @@ public class OreSiService { ReferenceImporterContext.Column::getExpectedHeader, Function.identity() )); - + final ReferenceImporterContext.Constants constants = new ReferenceImporterContext.Constants( + app.getId(), + conf, + refType, + repo.getRepository(app).referenceValue()); + /* final Set<Object> patternColumns = constants.getPatternColumns() + .map(pt -> pt.values()) + .flatMap(Collection::stream) + .stream().collect(Collectors.toSet());*/ + Set<String> patternColumns = constants.getPatternColumns() + .map(m->m.values().stream().flatMap(List::stream).collect(Collectors.toSet())) + .orElseGet(HashSet::new); + final Map<String, String> referenceToColumnName = lineCheckers.stream() + .filter(ReferenceLineChecker.class::isInstance) + .map(ReferenceLineChecker.class::cast) + .collect(Collectors.toMap(ReferenceLineChecker::getRefType, referenceLineChecker -> ((ReferenceColumn) ((ReferenceLineChecker) lineCheckers.asList().get(0)).getTarget().getTarget()).getColumn())); + final Map<String, Map<String, Map<String, String>>> displayByReferenceAndNaturalKey = + lineCheckers.stream() + .filter(ReferenceLineChecker.class::isInstance) + .map(ReferenceLineChecker.class::cast) + .map(ReferenceLineChecker::getRefType) + .filter(rt -> patternColumns.contains(rt)) + .collect(Collectors.toMap(ref -> referenceToColumnName.getOrDefault(ref, ref), ref -> repo.getRepository(app).referenceValue().findDisplayByNaturalKey(ref))); final ReferenceImporterContext referenceImporterContext = new ReferenceImporterContext( - app.getId(), - conf, - refType, + constants, lineCheckers, storedReferences, - columns + columns, + displayByReferenceAndNaturalKey ); return referenceImporterContext; } @@ -1408,4 +1371,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/ReferenceImporter.java b/src/main/java/fr/inra/oresing/rest/ReferenceImporter.java index 4b3433c46..37ad67222 100644 --- a/src/main/java/fr/inra/oresing/rest/ReferenceImporter.java +++ b/src/main/java/fr/inra/oresing/rest/ReferenceImporter.java @@ -44,18 +44,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.UUID; +import java.util.*; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -76,6 +65,10 @@ abstract class ReferenceImporter { } } + public String getDisplayByReferenceAndNaturalKey(String referencedColumn, String naturalKey, String locale){ + return referenceImporterContext.getDisplayByReferenceAndNaturalKey(referencedColumn, naturalKey, locale); + } + /** * Importer le fichier passé en paramètre. * @@ -290,7 +283,7 @@ abstract class ReferenceImporter { recursionStrategy.getKnownId(naturalKey) .ifPresent(e::setId); final Ltree hierarchicalReference = recursionStrategy.getHierarchicalReference(naturalKey); - referenceDatum.putAll(InternationalizationDisplay.getDisplays(referenceImporterContext.getDisplayPattern(), referenceImporterContext.getDisplayColumns(), referenceDatum)); + referenceDatum.putAll(InternationalizationDisplay.getDisplays(referenceImporterContext, referenceDatum)); /** * on remplace l'id par celle en base si elle existe @@ -493,4 +486,4 @@ abstract class ReferenceImporter { return streamBeforePreloading; } } -} +} \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/rest/ReferenceImporterContext.java b/src/main/java/fr/inra/oresing/rest/ReferenceImporterContext.java index ae0d71e64..958292ab5 100644 --- a/src/main/java/fr/inra/oresing/rest/ReferenceImporterContext.java +++ b/src/main/java/fr/inra/oresing/rest/ReferenceImporterContext.java @@ -2,94 +2,45 @@ package fr.inra.oresing.rest; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.MoreCollectors; -import com.google.common.collect.SetMultimap; +import com.google.common.collect.*; import fr.inra.oresing.checker.LineChecker; import fr.inra.oresing.checker.ReferenceLineChecker; -import fr.inra.oresing.model.ColumnPresenceConstraint; -import fr.inra.oresing.model.Configuration; -import fr.inra.oresing.model.ReferenceColumn; -import fr.inra.oresing.model.ReferenceColumnIndexedValue; -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.*; import fr.inra.oresing.model.internationalization.Internationalization; import fr.inra.oresing.model.internationalization.InternationalizationDisplay; import fr.inra.oresing.model.internationalization.InternationalizationMap; import fr.inra.oresing.model.internationalization.InternationalizationReferenceMap; import fr.inra.oresing.persistence.Ltree; +import fr.inra.oresing.persistence.ReferenceValueRepository; import lombok.AllArgsConstructor; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; /** * Toutes les informations nécessaires à l'import d'un référentiel donné. - * + * <p> * C'est un objet immuable, toutes ces informations sont constantes tout au long de l'import; */ @AllArgsConstructor public class ReferenceImporterContext { - private static final String COMPOSITE_NATURAL_KEY_COMPONENTS_SEPARATOR = "__"; - - /** - * Identifiant de l'application à laquelle le référentiel importé appartient - */ - private final UUID applicationId; - - /** - * La configuration de l'application qui contient le référentiel mais aussi les utilisations de ce référentiel - */ - private final Configuration conf; - - /** - * Le nom du référentiel - */ - private final String refType; - + private final Constants constants; /** * Tous les {@link LineChecker} qui s'appliquent sur chaque ligne à importer */ private final ImmutableSet<LineChecker> lineCheckers; - /** * Les clés techniques de chaque clé naturelle hiérarchique de toutes les lignes existantes en base (avant l'import) */ private final ImmutableMap<Ltree, UUID> storedReferences; - private final ImmutableMap<String, Column> columnsPerHeader; + Map<String, Map<String, Map<String, String>>> displayByReferenceAndNaturalKey; - private Optional<InternationalizationReferenceMap> getInternationalizationReferenceMap() { - Optional<InternationalizationReferenceMap> internationalizationReferenceMap = Optional.ofNullable(conf) - .map(Configuration::getInternationalization) - .map(InternationalizationMap::getReferences) - .map(references -> references.getOrDefault(refType, null)); - return internationalizationReferenceMap; - } - - public Map<String, Internationalization> getDisplayColumns() { - Optional<InternationalizationReferenceMap> internationalizationReferenceMap = getInternationalizationReferenceMap(); - return internationalizationReferenceMap - .map(InternationalizationReferenceMap::getInternationalizedColumns) - .orElseGet(HashMap::new); - } - - public Optional<Map<String, String>> getDisplayPattern() { - Optional<InternationalizationReferenceMap> internationalizationReferenceMap = getInternationalizationReferenceMap(); - return internationalizationReferenceMap - .map(InternationalizationReferenceMap::getInternationalizationDisplay) - .map(InternationalizationDisplay::getPattern); + public String getDisplayByReferenceAndNaturalKey(String referencedColumn, String naturalKey, String locale){ + return this.displayByReferenceAndNaturalKey.getOrDefault(referencedColumn, new HashMap<>()) + .getOrDefault(naturalKey, new HashMap<>()) + .getOrDefault(locale, naturalKey); } /** @@ -102,17 +53,12 @@ public class ReferenceImporterContext { return COMPOSITE_NATURAL_KEY_COMPONENTS_SEPARATOR; } - private HierarchicalKeyFactory getHierarchicalKeyFactory() { - HierarchicalKeyFactory hierarchicalKeyFactory = HierarchicalKeyFactory.build(conf, refType); - return hierarchicalKeyFactory; - } - public String getRefType() { - return refType; + return constants.getRefType(); } public Ltree getRefTypeAsLabel() { - return Ltree.fromUnescapedString(refType); + return Ltree.fromUnescapedString(getRefType()); } /** @@ -122,6 +68,10 @@ public class ReferenceImporterContext { return getHierarchicalKeyFactory().newHierarchicalKey(recursiveNaturalKey, referenceDatum); } + private HierarchicalKeyFactory getHierarchicalKeyFactory() { + return constants.getHierarchicalKeyFactory(); + } + /** * Crée une nom de référentiel hiérarchique */ @@ -140,12 +90,11 @@ public class ReferenceImporterContext { } private Configuration.ReferenceDescription getRef() { - Configuration.ReferenceDescription ref = conf.getReferences().get(refType); - return ref; + return constants.getRef(); } private Optional<Configuration.CompositeReferenceComponentDescription> getRecursiveComponentDescription() { - return conf.getCompositeReferences().values().stream() + return constants.getConf().getCompositeReferences().values().stream() .map(compositeReferenceDescription -> compositeReferenceDescription.getComponents().stream().filter(compositeReferenceComponentDescription -> getRefType().equals(compositeReferenceComponentDescription.getReference()) && compositeReferenceComponentDescription.getParentRecursiveKey() != null).findFirst().orElse(null)) .filter(e -> e != null) .findFirst(); @@ -193,7 +142,7 @@ public class ReferenceImporterContext { } public UUID getApplicationId() { - return applicationId; + return constants.getApplicationId(); } public Optional<UUID> getIdForSameHierarchicalKeyInDatabase(Ltree hierarchicalKey) { @@ -221,6 +170,124 @@ public class ReferenceImporterContext { return column.getCsvCellContent(referenceDatum); } + public Optional<Map<String, String>> getDisplayPattern() { + return constants.getDisplayPattern(); + } + + public Map<String, Internationalization> getDisplayColumns() { + return constants.getDisplayColumns(); + } + + public static class Constants { + /** + * Identifiant de l'application à laquelle le référentiel importé appartient + */ + private final UUID applicationId; + /** + * La configuration de l'application qui contient le référentiel mais aussi les utilisations de ce référentiel + */ + private final Configuration conf; + /** + * Le nom du référentiel + */ + private final String refType; + private final Optional<InternationalizationReferenceMap> internationalizationReferenceMap; + private final Map<String, Internationalization> displayColumns; + private final Optional<Map<String, String>> displayPattern; + private final HierarchicalKeyFactory hierarchicalKeyFactory; + private final Optional<Map<String, List<String>>> patternColumns; + private final Optional<Map<String, List<InternationalizationDisplay.PatternSection>>> patternSection; + Constants constants; + + public Constants(UUID applicationId, Configuration conf, String refType, ReferenceValueRepository referenceValueRepository) { + this.applicationId = applicationId; + this.conf = conf; + this.refType = refType; + this.internationalizationReferenceMap = buildInternationalizationReferenceMap(conf, refType); + this.displayColumns = buildDisplayColumns(); + this.displayPattern = buildDisplayPattern(); + this.hierarchicalKeyFactory = buildHierarchicalKeyFactory(); + this.patternColumns = this.buildPatternColumns(); + this.patternSection = this.buildPatternSection(); + } + + public Configuration.ReferenceDescription getRef() { + return conf.getReferences().get(refType); + } + + private Optional<InternationalizationReferenceMap> buildInternationalizationReferenceMap(Configuration conf, String refType) { + Optional<InternationalizationReferenceMap> internationalizationReferenceMap = Optional.ofNullable(conf) + .map(Configuration::getInternationalization) + .map(InternationalizationMap::getReferences) + .map(references -> references.getOrDefault(refType, null)); + return internationalizationReferenceMap; + } + + private Map<String, Internationalization> buildDisplayColumns() { + return this.internationalizationReferenceMap + .map(InternationalizationReferenceMap::getInternationalizedColumns) + .orElseGet(HashMap::new); + } + + private Optional<Map<String, String>> buildDisplayPattern() { + return this.internationalizationReferenceMap + .map(InternationalizationReferenceMap::getInternationalizationDisplay) + .map(InternationalizationDisplay::getPattern); + } + + + private HierarchicalKeyFactory buildHierarchicalKeyFactory() { + HierarchicalKeyFactory hierarchicalKeyFactory = HierarchicalKeyFactory.build(conf, refType); + return hierarchicalKeyFactory; + } + + private Optional<Map<String, List<InternationalizationDisplay.PatternSection>>> buildPatternSection() { + return displayPattern + .map(dp -> dp.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, k -> InternationalizationDisplay.parsePattern(k.getValue())))); + } + + private Optional<Map<String, List<String>>> buildPatternColumns() { + return displayPattern + .map(dp -> dp.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, k -> InternationalizationDisplay.getPatternColumns(k.getValue())))); + } + + public UUID getApplicationId() { + return applicationId; + } + + public Configuration getConf() { + return conf; + } + + public String getRefType() { + return refType; + } + + public Optional<InternationalizationReferenceMap> getInternationalizationReferenceMap() { + return internationalizationReferenceMap; + } + + public Map<String, Internationalization> getDisplayColumns() { + return displayColumns; + } + + public Optional<Map<String, String>> getDisplayPattern() { + return displayPattern; + } + + public HierarchicalKeyFactory getHierarchicalKeyFactory() { + return hierarchicalKeyFactory; + } + + public Optional<Map<String, List<String>>> getPatternColumns() { + return patternColumns; + } + + public Optional<Map<String, List<InternationalizationDisplay.PatternSection>>> getPatternSection() { + return patternSection; + } + } + /** * Contrat permettant de créer pour chaque ligne de référentiel sa clé hiérarchique. * <p> @@ -455,4 +522,4 @@ public class ReferenceImporterContext { return referenceColumnIndexedValue.getValues().get(expectedHierarchicalKey); } } -} +} \ No newline at end of file diff --git a/src/test/resources/data/acbb/acbb.yaml b/src/test/resources/data/acbb/acbb.yaml index 6ac07a6c7..81e64cd6f 100644 --- a/src/test/resources/data/acbb/acbb.yaml +++ b/src/test/resources/data/acbb/acbb.yaml @@ -86,6 +86,14 @@ references: nom_fr: nom_en: modalites: + internationalizedColumns: + nom_fr: + fr: nom_fr + en: nom_en + internationalizationDisplay: + pattern: + fr: '{nom_fr} ({code})' + en: '{nom_fr} ({code})' keyColumns: [code] columns: Variable de forcage: @@ -96,6 +104,10 @@ references: description_en: version_de_traitement: keyColumns: [site, traitement] + internationalizationDisplay: + pattern: + fr: '{traitement} ({modalites})' + en: '{traitement} ({modalites})' columns: site: traitement: -- GitLab From c9c13af3130bba29f285cfbff4f34622534ed0a3 Mon Sep 17 00:00:00 2001 From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr> Date: Tue, 22 Mar 2022 10:58:01 +0100 Subject: [PATCH 3/3] =?UTF-8?q?Correction=20(copi=C3=A9=20coll=C3=A9=20pas?= =?UTF-8?q?=20bon)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/fr/inra/oresing/rest/OreSiService.java | 2 +- 1 file changed, 1 insertion(+), 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 845e2dc27..cd64b03e3 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiService.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java @@ -401,7 +401,7 @@ public class OreSiService { final Map<String, String> referenceToColumnName = lineCheckers.stream() .filter(ReferenceLineChecker.class::isInstance) .map(ReferenceLineChecker.class::cast) - .collect(Collectors.toMap(ReferenceLineChecker::getRefType, referenceLineChecker -> ((ReferenceColumn) ((ReferenceLineChecker) lineCheckers.asList().get(0)).getTarget().getTarget()).getColumn())); + .collect(Collectors.toMap(ReferenceLineChecker::getRefType, referenceLineChecker -> ((ReferenceColumn) referenceLineChecker.getTarget().getTarget()).getColumn())); final Map<String, Map<String, Map<String, String>>> displayByReferenceAndNaturalKey = lineCheckers.stream() .filter(ReferenceLineChecker.class::isInstance) -- GitLab