diff --git a/src/main/java/fr/inra/oresing/model/ReferenceValue.java b/src/main/java/fr/inra/oresing/model/ReferenceValue.java index 88ea349bd3c437cc432df7d6be65c71da3035b4c..9a0b18b5408b3eff70590ab2e6e033b9eb9b831e 100644 --- a/src/main/java/fr/inra/oresing/model/ReferenceValue.java +++ b/src/main/java/fr/inra/oresing/model/ReferenceValue.java @@ -1,5 +1,6 @@ package fr.inra.oresing.model; +import fr.inra.oresing.persistence.Ltree; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -14,9 +15,9 @@ import java.util.UUID; public class ReferenceValue extends OreSiEntity { private UUID application; private String referenceType; - private String hierarchicalKey; - private String hierarchicalReference; - private String naturalKey; + private Ltree hierarchicalKey; + private Ltree hierarchicalReference; + private Ltree naturalKey; private Map<String, String> refValues; private Map<String, Set<UUID>> refsLinkedTo; private UUID binaryFile; diff --git a/src/main/java/fr/inra/oresing/persistence/JsonRowMapper.java b/src/main/java/fr/inra/oresing/persistence/JsonRowMapper.java index 75c99bd50a6eb4b08a4b6e01499e25a86c21cc06..10a0fc0623d09fa9d0df07f4242274f398f5634f 100644 --- a/src/main/java/fr/inra/oresing/persistence/JsonRowMapper.java +++ b/src/main/java/fr/inra/oresing/persistence/JsonRowMapper.java @@ -55,6 +55,18 @@ public class JsonRowMapper<T> implements RowMapper<T> { return LocalDateTimeRange.parseSql(p.getText()); } }) + .addSerializer(Ltree.class, new JsonSerializer<>() { + @Override + public void serialize(Ltree value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeString(value.getSql()); + } + }) + .addDeserializer(Ltree.class, new JsonDeserializer<>() { + @Override + public Ltree deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + return Ltree.fromSql(p.getText()); + } + }) ; jsonMapper.registerModule(module); } diff --git a/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java b/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java index fcd7c5902ec293363341fd9f6071aab11447d9f2..e74a926d3fdee3ac1f0fdbf7c3a266d69b36d761 100644 --- a/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java +++ b/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java @@ -55,6 +55,7 @@ abstract class JsonTableRepositoryTemplate<T extends OreSiEntity> implements Ini } }); String json = getJsonRowMapper().toJson(entities); + System.out.println("machin " + json); List<UUID> result = namedParameterJdbcTemplate.queryForList( query, new MapSqlParameterSource("json", json), UUID.class); }); diff --git a/src/main/java/fr/inra/oresing/persistence/Ltree.java b/src/main/java/fr/inra/oresing/persistence/Ltree.java new file mode 100644 index 0000000000000000000000000000000000000000..a13148ef3dbc45020ae5233550f5ab6230437775 --- /dev/null +++ b/src/main/java/fr/inra/oresing/persistence/Ltree.java @@ -0,0 +1,100 @@ +package fr.inra.oresing.persistence; + +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import lombok.Value; +import org.apache.commons.lang3.CharUtils; +import org.apache.commons.lang3.RegExUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.UUID; +import java.util.stream.Collectors; + +@Value +public class Ltree { + + /** + * Déliminateur entre les différents niveaux d'un ltree postgresql. + * <p> + * https://www.postgresql.org/docs/current/ltree.html + */ + public static final String SEPARATOR = "."; + + String sql; + + private Ltree(String sql) { + this.sql = sql; + } + + public static Ltree fromSql(String sql) { + checkSyntax(sql); + return new Ltree(sql); + } + + public static String escapeLabel(String key) { + String lowerCased = key.toLowerCase(); + String withAccentsStripped = StringUtils.stripAccents(lowerCased); + String toEscape = StringUtils.replace(withAccentsStripped, " ", "_"); + String escaped = toEscape.chars() + .mapToObj(x -> (char) x) + .map(Ltree::escapeSymbolFromKeyComponent) + .collect(Collectors.joining()); + checkLabelSyntax(escaped); + return escaped; + } + + public static void checkLabelSyntax(String keyComponent) { + Preconditions.checkState(keyComponent.length() <= 256, "Un label dans un ltree ne peut pas être plus long que 256 caractères à cause de PG"); + Preconditions.checkState(!keyComponent.isEmpty(), "La clé naturelle ne peut être vide. vérifier le nom des colonnes."); + Preconditions.checkState(keyComponent.matches("[a-zA-Z0-9_]+"), keyComponent + " n'est pas un élément valide pour une clé naturelle"); + } + + private static String escapeSymbolFromKeyComponent(Character aChar) { + String escapedChar; + if (characterCanBeUsedInLabel(aChar)) { + escapedChar = CharUtils.toString(aChar); + } else { + escapedChar = RegExUtils.replaceAll( + Character.getName(aChar), + "[^a-zA-Z0-9_]", + "" + ); + } + return escapedChar; + } + + /** + * D'après la documentation PostgreSQL sur ltree + * + * <blockquote> + * A label is a sequence of alphanumeric characters and underscores (for example, in C locale the characters A-Za-z0-9_ are allowed). Labels must be less than 256 characters long. + * </blockquote> + */ + private static boolean characterCanBeUsedInLabel(Character aChar) { + return CharUtils.isAsciiAlphanumeric(aChar) || '_' == aChar; + } + + public static void checkSyntax(String sql) { + Splitter.on(SEPARATOR).split(sql).forEach(Ltree::checkLabelSyntax); + } + + public static Ltree join(String prefix, String suffix) { + checkSyntax(prefix); + checkSyntax(suffix); + return fromSql(prefix + SEPARATOR + suffix); + } + + public static Ltree join(Ltree prefix, Ltree suffix) { + return join(prefix.getSql(), suffix.getSql()); + } + + public static Ltree parseLabel(String labelToEscape) { + String escaped = escapeLabel(labelToEscape); + return fromSql(escaped); + } + + public static Ltree toLabel(UUID uuid) { + String escaped = escapeLabel(StringUtils.remove(uuid.toString(), "-")); + return fromSql(escaped); + } +} diff --git a/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java b/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java index f97c428e212307784a5db136419cf92b5cd4b50e..7b24cf31cf405daa794ec2f184fbef8286a0d3ae 100644 --- a/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java +++ b/src/main/java/fr/inra/oresing/persistence/ReferenceValueRepository.java @@ -115,11 +115,11 @@ public class ReferenceValueRepository extends JsonTableInApplicationSchemaReposi public ImmutableMap<String, ApplicationResult.Reference.ReferenceUUIDAndDisplay> getReferenceIdAndDisplayPerKeys(String referenceType, String locale) { return findAllByReferenceType(referenceType).stream() - .collect(ImmutableMap.toImmutableMap(ReferenceValue::getHierarchicalKey,result->new ApplicationResult.Reference.ReferenceUUIDAndDisplay(result.getRefValues().get("__display_"+locale), result.getId(), result.getRefValues()))); + .collect(ImmutableMap.toImmutableMap(referenceValue -> referenceValue.getHierarchicalKey().getSql(),result->new ApplicationResult.Reference.ReferenceUUIDAndDisplay(result.getRefValues().get("__display_"+locale), result.getId(), result.getRefValues()))); } public ImmutableMap<String, UUID> getReferenceIdPerKeys(String referenceType) { return findAllByReferenceType(referenceType).stream() - .collect(ImmutableMap.toImmutableMap(ReferenceValue::getHierarchicalKey, ReferenceValue::getId)); + .collect(ImmutableMap.toImmutableMap(referenceValue -> referenceValue.getHierarchicalKey().getSql(), ReferenceValue::getId)); } } \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/rest/AuthorizationService.java b/src/main/java/fr/inra/oresing/rest/AuthorizationService.java index a667a59a9f69c7a5ef8776b796392ab72f9ab92b..7223f5651212088e7c0509e265b308b2186dc8af 100644 --- a/src/main/java/fr/inra/oresing/rest/AuthorizationService.java +++ b/src/main/java/fr/inra/oresing/rest/AuthorizationService.java @@ -300,6 +300,6 @@ public class AuthorizationService { ImmutableSortedSet<GetGrantableResult.AuthorizationScope.Option> options = tree.getChildren(referenceValue).stream() .map(child -> toOption(tree, child)) .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.AuthorizationScope.Option::getId))); - return new GetGrantableResult.AuthorizationScope.Option(referenceValue.getHierarchicalKey(), referenceValue.getHierarchicalKey(), options); + return new GetGrantableResult.AuthorizationScope.Option(referenceValue.getHierarchicalKey().getSql(), referenceValue.getHierarchicalKey().getSql(), options); } } \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java index d59af7505e474d2efccc7bf38bdbb98b9d317fbb..e8cb0de81f4007d373437bbc53912056c470c2b7 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java @@ -197,9 +197,9 @@ public class OreSiResources { ImmutableSet<GetReferenceResult.ReferenceValue> referenceValues = list.stream() .map(referenceValue -> new GetReferenceResult.ReferenceValue( - referenceValue.getHierarchicalKey(), - referenceValue.getHierarchicalReference(), - referenceValue.getNaturalKey(), + referenceValue.getHierarchicalKey().getSql(), + referenceValue.getHierarchicalReference().getSql(), + referenceValue.getNaturalKey().getSql(), referenceValue.getRefValues() ) ) diff --git a/src/main/java/fr/inra/oresing/rest/OreSiService.java b/src/main/java/fr/inra/oresing/rest/OreSiService.java index aa3c7c3807481436c10ddbec7ed85caff5bfc8e5..60d074e345cc21bcf97389dbefea3805b6da1381 100644 --- a/src/main/java/fr/inra/oresing/rest/OreSiService.java +++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java @@ -3,7 +3,6 @@ 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.base.Splitter; import com.google.common.collect.*; import com.google.common.primitives.Ints; import fr.inra.oresing.OreSiTechnicalException; @@ -25,7 +24,6 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.csv.CSVRecord; -import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.StringUtils; import org.assertj.core.util.Streams; import org.assertj.core.util.Strings; @@ -66,12 +64,6 @@ public class OreSiService { public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss").withZone(ZoneOffset.UTC); public static final DateTimeFormatter DATE_FORMATTER_DDMMYYYY = DateTimeFormatter.ofPattern("dd/MM/yyyy"); - /** - * Déliminateur entre les différents niveaux d'un ltree postgresql. - * <p> - * https://www.postgresql.org/docs/current/ltree.html - */ - private static final String LTREE_SEPARATOR = "."; private static final String KEYCOLUMN_SEPARATOR = "__"; @Autowired private OreSiRepository repo; @@ -97,27 +89,12 @@ public class OreSiService { @Autowired private RelationalService relationalService; + /** + * @deprecated utiliser directement {@link Ltree#escapeLabel(String)} + */ + @Deprecated public static String escapeKeyComponent(String key) { - String toEscape = StringUtils.stripAccents(key.toLowerCase()); - String escaped = StringUtils.remove( - RegExUtils.replaceAll( - StringUtils.replace(toEscape, " ", "_"), - "[^a-z0-9_]", - "" - ), "-" - ); - checkNaturalKeySyntax(escaped); - return escaped; - } - - public static void checkNaturalKeySyntax(String keyComponent) { - if (keyComponent.isEmpty()) - Preconditions.checkState(keyComponent.matches("[a-z0-9_]+"), "La clé naturelle ne peut être vide. vérifier le nom des colonnes."); - Preconditions.checkState(keyComponent.matches("[a-z0-9_]+"), keyComponent + " n'est pas un élément valide pour une clé naturelle"); - } - - private void checkHierarchicalKeySyntax(String compositeKey) { - Splitter.on(LTREE_SEPARATOR).split(compositeKey).forEach(OreSiService::checkNaturalKeySyntax); + return Ltree.escapeLabel(key); } protected UUID storeFile(Application app, MultipartFile file) throws IOException { @@ -339,10 +316,10 @@ public class OreSiService { String parentHierarchicalKeyColumn, parentHierarchicalParentReference; Optional<Configuration.CompositeReferenceComponentDescription> recursiveComponentDescription = getRecursiveComponent(conf.getCompositeReferences(), refType); boolean isRecursive = recursiveComponentDescription.isPresent(); - BiFunction<String, Map<String, String>, String> getHierarchicalKeyFn; - Function<String, String> getHierarchicalReferenceFn; - Map<String, String> buildedHierarchicalKeys = new HashMap<>(); - Map<String, String> parentreferenceMap = new HashMap<>(); + BiFunction<Ltree, Map<String, String>, Ltree> getHierarchicalKeyFn; + Function<Ltree, Ltree> getHierarchicalReferenceFn; + Map<Ltree, Ltree> buildedHierarchicalKeys = new HashMap<>(); + Map<Ltree, Ltree> parentreferenceMap = new HashMap<>(); if (toUpdateCompositeReference.isPresent()) { Configuration.CompositeReferenceDescription compositeReferenceDescription = toUpdateCompositeReference.get(); boolean root = Iterables.get(compositeReferenceDescription.getComponents(), 0).getReference().equals(refType); @@ -356,10 +333,10 @@ public class OreSiService { parentHierarchicalKeyColumn = referenceComponentDescription.getParentKeyColumn(); parentHierarchicalParentReference = compositeReferenceDescription.getComponents().get(compositeReferenceDescription.getComponents().indexOf(referenceComponentDescription) - 1).getReference(); getHierarchicalKeyFn = (naturalKey, referenceValues) -> { - String parentHierarchicalKey = escapeKeyComponent(referenceValues.get(parentHierarchicalKeyColumn)); - return parentHierarchicalKey + LTREE_SEPARATOR + naturalKey; + Ltree parentHierarchicalKey = Ltree.parseLabel(referenceValues.get(parentHierarchicalKeyColumn)); + return Ltree.join(parentHierarchicalKey, naturalKey); }; - getHierarchicalReferenceFn = (reference) -> parentHierarchicalParentReference + LTREE_SEPARATOR + reference; + getHierarchicalReferenceFn = (reference) -> Ltree.join(Ltree.parseLabel(parentHierarchicalParentReference), reference); } } else { getHierarchicalKeyFn = (naturalKey, referenceValues) -> naturalKey; @@ -391,7 +368,7 @@ public class OreSiService { if (isRecursive) { recordStream = addMissingReferences(recordStream, selfLineChecker, recursiveComponentDescription, columns, ref, parentreferenceMap); } - List<String> hierarchicalKeys = new LinkedList<>(); + List<Ltree> hierarchicalKeys = new LinkedList<>(); Optional<InternationalizationReferenceMap> internationalizationReferenceMap = Optional.ofNullable(conf) .map(configuration -> conf.getInternationalization()) .map(inter -> inter.getReferences()) @@ -415,7 +392,7 @@ public class OreSiService { UUID referenceId = referenceValidationCheckResult.getReferenceId(); refValues.put((String) referenceValidationCheckResult.getTarget().getTarget(), (String) referenceValidationCheckResult.getValue()); refsLinkedTo - .computeIfAbsent(escapeKeyComponent(reference), k -> new LinkedHashSet<>()) + .computeIfAbsent(Ltree.escapeLabel(reference), k -> new LinkedHashSet<>()) .add(referenceId); } } else { @@ -423,43 +400,46 @@ public class OreSiService { } }); ReferenceValue e = new ReferenceValue(); - String naturalKey; - String technicalId = e.getId().toString(); + Ltree naturalKey; if (ref.getKeyColumns().isEmpty()) { - naturalKey = escapeKeyComponent(technicalId); + UUID technicalId = e.getId(); + naturalKey = Ltree.toLabel(technicalId); } else { - naturalKey = ref.getKeyColumns().stream() + naturalKey = Ltree.parseLabel(ref.getKeyColumns().stream() .map(kc -> refValues.get(kc)) .filter(key -> !Strings.isNullOrEmpty(key)) - .map(key -> escapeKeyComponent(key)) - .collect(Collectors.joining(KEYCOLUMN_SEPARATOR)); + .map(key -> Ltree.escapeLabel(key)) + .collect(Collectors.joining(KEYCOLUMN_SEPARATOR))); } - OreSiService.checkNaturalKeySyntax(naturalKey); - String recursiveNaturalKey = naturalKey; + Ltree recursiveNaturalKey = naturalKey; + final Ltree refTypeAsLabel = Ltree.parseLabel(refType); if (isRecursive) { selfLineChecker .map(referenceLineChecker -> referenceLineChecker.getReferenceValues()) - .map(values -> values.get(naturalKey)) + .map(values -> values.get(naturalKey.getSql())) .filter(key -> key != null) .ifPresent(key -> e.setId(key)); - String parentKey = parentreferenceMap.getOrDefault(recursiveNaturalKey, null); - while (!Strings.isNullOrEmpty(parentKey)) { - recursiveNaturalKey = parentKey + LTREE_SEPARATOR + recursiveNaturalKey; + Ltree parentKey = parentreferenceMap.getOrDefault(recursiveNaturalKey, null); + while (parentKey != null) { + recursiveNaturalKey = Ltree.join(parentKey, recursiveNaturalKey); parentKey = parentreferenceMap.getOrDefault(parentKey, null); + //selfHierarchicalReference = Ltree.join(selfHierarchicalReference, refTypeAsLabel); } +// int x = StringUtils.countMatches(selfHierarchicalReference.getSql(), "."); +// int y = StringUtils.countMatches(recursiveNaturalKey.getSql(), "."); +// Preconditions.checkState(x == y); } - String hierarchicalKey = getHierarchicalKeyFn.apply(isRecursive ? recursiveNaturalKey : naturalKey, refValues); - String selfHierarchicalReference = refType; + Ltree hierarchicalKey = getHierarchicalKeyFn.apply(isRecursive ? recursiveNaturalKey : naturalKey, refValues); + Ltree selfHierarchicalReference = refTypeAsLabel; if (isRecursive) { - for (int i = 1; i < recursiveNaturalKey.split("\\.").length; i++) { - selfHierarchicalReference += ".".concat(refType); + for (int i = 1; i < recursiveNaturalKey.getSql().split("\\.").length; i++) { + selfHierarchicalReference = Ltree.fromSql(selfHierarchicalReference.getSql() + ".".concat(refType)); } } - String hierarchicalReference = + Ltree hierarchicalReference = getHierarchicalReferenceFn.apply(selfHierarchicalReference); refValues.putAll(InternationalizationDisplay.getDisplays(displayPattern, displayColumns, refValues)); buildedHierarchicalKeys.put(naturalKey, hierarchicalKey); - checkHierarchicalKeySyntax(hierarchicalKey); e.setBinaryFile(fileId); e.setReferenceType(refType); e.setHierarchicalKey(hierarchicalKey); @@ -470,7 +450,7 @@ public class OreSiService { e.setRefValues(refValues); return e; }) - .sorted((a, b) -> a.getHierarchicalKey().compareTo(b.getHierarchicalKey())) + .sorted(Comparator.comparing(a -> a.getHierarchicalKey().getSql())) .map(e -> { if (hierarchicalKeys.contains(e.getHierarchicalKey())) { /*envoyer un message de warning : le refType avec la clef e.getNaturalKey existe en plusieurs exemplaires @@ -491,7 +471,7 @@ public class OreSiService { return fileId; } - private Stream<CSVRecord> addMissingReferences(Stream<CSVRecord> recordStream, Optional<ReferenceLineChecker> selfLineChecker, Optional<Configuration.CompositeReferenceComponentDescription> recursiveComponentDescription, ImmutableList<String> columns, Configuration.ReferenceDescription ref, Map<String, String> referenceMap) { + private Stream<CSVRecord> addMissingReferences(Stream<CSVRecord> recordStream, Optional<ReferenceLineChecker> selfLineChecker, Optional<Configuration.CompositeReferenceComponentDescription> recursiveComponentDescription, ImmutableList<String> columns, Configuration.ReferenceDescription ref, Map<Ltree, Ltree> referenceMap) { Integer parentRecursiveIndex = recursiveComponentDescription .map(rcd -> rcd.getParentRecursiveKey()) .map(rck -> columns.indexOf(rck)) @@ -509,16 +489,16 @@ public class OreSiService { if (!Strings.isNullOrEmpty(s)) { String naturalKey; try { - s = OreSiService.escapeKeyComponent(s); + s = Ltree.escapeLabel(s); naturalKey = ref.getKeyColumns() .stream() .map(kc -> columns.indexOf(kc)) - .map(k -> OreSiService.escapeKeyComponent(csvrecord.get(k))) + .map(k -> Ltree.escapeLabel(csvrecord.get(k))) .collect(Collectors.joining("__")); } catch (IllegalArgumentException e) { return; } - referenceMap.put(naturalKey, s); + referenceMap.put(Ltree.parseLabel(naturalKey), Ltree.parseLabel(s)); if (!referenceUUIDs.containsKey(s)) { referenceUUIDs.put(s, UUID.randomUUID()); } @@ -547,8 +527,8 @@ public class OreSiService { .getConfiguration() .getCompositeReferencesUsing(lowestLevelReference) .orElseThrow(); - BiMap<String, ReferenceValue> indexedByHierarchicalKeyReferenceValues = HashBiMap.create(); - Map<ReferenceValue, String> parentHierarchicalKeys = new LinkedHashMap<>(); + BiMap<Ltree, ReferenceValue> indexedByHierarchicalKeyReferenceValues = HashBiMap.create(); + Map<ReferenceValue, Ltree> parentHierarchicalKeys = new LinkedHashMap<>(); ImmutableList<String> referenceTypes = compositeReferenceDescription.getComponents().stream() .map(Configuration.CompositeReferenceComponentDescription::getReference) .collect(ImmutableList.toImmutableList()); @@ -562,7 +542,7 @@ public class OreSiService { referenceValueRepository.findAllByReferenceType(reference).forEach(referenceValue -> { indexedByHierarchicalKeyReferenceValues.put(referenceValue.getHierarchicalKey(), referenceValue); if (parentKeyColumn != null) { - String parentHierarchicalKey = referenceValue.getRefValues().get(parentKeyColumn); + Ltree parentHierarchicalKey = Ltree.fromSql(referenceValue.getRefValues().get(parentKeyColumn)); parentHierarchicalKeys.put(referenceValue, parentHierarchicalKey); } }); @@ -803,7 +783,7 @@ public class OreSiService { Map<String, String> requiredAuthorizations = new LinkedHashMap<>(); dataTypeDescription.getAuthorization().getAuthorizationScopes().forEach((authorizationScope, variableComponentKey) -> { String requiredAuthorization = values.get(variableComponentKey); - checkHierarchicalKeySyntax(requiredAuthorization); + Ltree.checkSyntax(requiredAuthorization); requiredAuthorizations.put(authorizationScope, requiredAuthorization); }); checkTimescopRangeInDatasetRange(timeScope, errors, binaryFileDataset, rowWithData.getLineNumber()); diff --git a/src/main/resources/migration/application/V1__init_schema.sql b/src/main/resources/migration/application/V1__init_schema.sql index 9a0db35f89163d7a0bd5f3b21c2d3bf7d32c7cb2..c493aa71c83ccd7b6ae57dca064cc340df7c04b8 100644 --- a/src/main/resources/migration/application/V1__init_schema.sql +++ b/src/main/resources/migration/application/V1__init_schema.sql @@ -19,8 +19,8 @@ create table ReferenceValue application EntityRef REFERENCES Application (id), referenceType TEXT CHECK (name_check(application, 'referenceType', referenceType)), hierarchicalKey ltree NOT NULL, - hierarchicalReference TEXT NOT NULL, - naturalKey TEXT NOT NULL, + hierarchicalReference ltree NOT NULL, + naturalKey ltree NOT NULL, refsLinkedTo jsonb check (refs_check_for_reference('${applicationSchema}', application, refsLinkedTo)), refValues jsonb, binaryFile EntityRef REFERENCES BinaryFile (id), diff --git a/src/test/java/fr/inra/oresing/persistence/LtreeTest.java b/src/test/java/fr/inra/oresing/persistence/LtreeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0e1479f09d707a2be397b7312ddcf454f566e6ba --- /dev/null +++ b/src/test/java/fr/inra/oresing/persistence/LtreeTest.java @@ -0,0 +1,15 @@ +package fr.inra.oresing.persistence; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LtreeTest { + + @Test + public void parseLabel() { + String sql = Ltree.parseLabel("composition <5%/µg").getSql(); + Assert.assertEquals("composition_LESSTHANSIGN5PERCENTSIGNSOLIDUSMICROSIGNg", sql); + } +} \ No newline at end of file diff --git a/src/test/resources/data/monsore/monsore-with-repository.yaml b/src/test/resources/data/monsore/monsore-with-repository.yaml index d6d75547133832529e287a2f1cdcfe0451c9b5ee..351da6ccafe82e0634ac03efe4eaf51a780e4d47 100644 --- a/src/test/resources/data/monsore/monsore-with-repository.yaml +++ b/src/test/resources/data/monsore/monsore-with-repository.yaml @@ -352,8 +352,8 @@ dataTypes: replace: true defaultValue: > return references.get("sites") - .find{it.getNaturalKey().equals(datumByVariableAndComponent.get("site").get("bassin"))} - .getHierarchicalKey(); + .find{it.getNaturalKey().getSql().equals(datumByVariableAndComponent.get("site").get("bassin"))} + .getHierarchicalKey().getSql(); checker: name: Reference params: @@ -365,7 +365,7 @@ dataTypes: defaultValue: > return references.get("sites") .find{it.getRefValues().get("zet_chemin_parent").equals(datumByVariableAndComponent.get("site").get("bassin")) && it.getRefValues().get("zet_nom_key").equals(datumByVariableAndComponent.get("site").get("plateforme"))} - .getHierarchicalKey(); + .getHierarchicalKey().getSql(); checker: name: Reference params: diff --git a/src/test/resources/data/monsore/monsore.yaml b/src/test/resources/data/monsore/monsore.yaml index f11cc867bbf1dfec7c93659be416bd85d305aaab..fec3bc30372e3b677a8c211b6342f0b425f83119 100644 --- a/src/test/resources/data/monsore/monsore.yaml +++ b/src/test/resources/data/monsore/monsore.yaml @@ -350,8 +350,8 @@ dataTypes: replace: true defaultValue: > return references.get("sites") - .find{it.getNaturalKey().equals(datumByVariableAndComponent.get("site").get("bassin"))} - .getHierarchicalKey(); + .find{it.getNaturalKey().getSql().equals(datumByVariableAndComponent.get("site").get("bassin"))} + .getHierarchicalKey().getSql(); checker: name: Reference params: @@ -363,7 +363,7 @@ dataTypes: defaultValue: > return references.get("sites") .find{it.getRefValues().get("zet_chemin_parent").equals(datumByVariableAndComponent.get("site").get("bassin")) && it.getRefValues().get("zet_nom_key").equals(datumByVariableAndComponent.get("site").get("plateforme"))} - .getHierarchicalKey(); + .getHierarchicalKey().getSql(); checker: name: Reference params: