From b421972b7140a84c287b0c836995487e99af0f55 Mon Sep 17 00:00:00 2001 From: lucile varloteaux <lucile.varloteaux@inrae.fr> Date: Tue, 14 Jan 2025 11:34:51 +0100 Subject: [PATCH 1/5] boulot vue avec philippe hier ^^ --- .../inra/oresing/domain/checker/LineChecker.java | 14 +++++--------- .../domain/data/DataColumnPatternValue.java | 1 + .../GroovyValidationCheckResult.java | 6 ++++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/fr/inra/oresing/domain/checker/LineChecker.java b/src/main/java/fr/inra/oresing/domain/checker/LineChecker.java index d4568db..d4bbc23 100644 --- a/src/main/java/fr/inra/oresing/domain/checker/LineChecker.java +++ b/src/main/java/fr/inra/oresing/domain/checker/LineChecker.java @@ -5,16 +5,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import fr.inra.oresing.domain.application.configuration.checker.CheckerDescription; import fr.inra.oresing.domain.application.configuration.checker.GroovyExpressionChecker; -import fr.inra.oresing.domain.checker.type.BooleanType; -import fr.inra.oresing.domain.checker.type.FieldType; -import fr.inra.oresing.domain.checker.type.ListType; -import fr.inra.oresing.domain.checker.type.StringType; +import fr.inra.oresing.domain.checker.type.*; import fr.inra.oresing.domain.data.*; import fr.inra.oresing.domain.data.deposit.PublishContext; -import fr.inra.oresing.domain.data.deposit.validation.validationcheckresults.DefaultManyValidationCheckResult; -import fr.inra.oresing.domain.data.deposit.validation.validationcheckresults.CheckerValidationCheckResult; -import fr.inra.oresing.domain.data.deposit.validation.validationcheckresults.DefaultCheckerValidationCheckResult; -import fr.inra.oresing.domain.data.deposit.validation.validationcheckresults.GroovyValidationCheckResult; +import fr.inra.oresing.domain.data.deposit.validation.validationcheckresults.*; import fr.inra.oresing.domain.groovy.BooleanGroovyExpression; import fr.inra.oresing.domain.groovy.Expression; import fr.inra.oresing.domain.groovy.GroovyDecorator; @@ -332,7 +326,9 @@ public sealed interface LineChecker<FT extends FieldType> permits LineChecker.Ma DataDatum transformedReferenceDatum = transformer().transform(referenceDatum, context); DataColumn column = target(); FieldType valuesToCheck = transformedReferenceDatum.getValuesToCheck(column); - return GroovyValidationCheckResult.success(target(), valuesToCheck); + return valuesToCheck instanceof PatternType patternType ? + PatternValidationCheckResult.of(GroovyValidationCheckResult.success(target(), valuesToCheck), patternType) + : GroovyValidationCheckResult.success(target(), valuesToCheck); } catch (GroovyException groovyException) { return GroovyValidationCheckResult.error(target(), groovyException.getMessage(), ImmutableMap.copyOf(groovyException.getParams())); } diff --git a/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java b/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java index fef44f1..03e38c6 100644 --- a/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java +++ b/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java @@ -29,6 +29,7 @@ public record DataColumnPatternValue( @Override public DataColumnPatternValue transform(final Function<FieldType, FieldType> transformation) { + final Map<Ltree, String> transformedValues = null;//Maps.transformValues(values, transformation::apply); return new DataColumnPatternValue((FieldType) null); } diff --git a/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java b/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java index 533d2e5..3f1a5c5 100644 --- a/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java +++ b/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java @@ -4,7 +4,9 @@ import com.google.common.collect.ImmutableMap; import fr.inra.oresing.ValidationLevel; import fr.inra.oresing.domain.checker.CheckerTarget; import fr.inra.oresing.domain.checker.type.FieldType; +import fr.inra.oresing.domain.checker.type.PatternType; import fr.inra.oresing.domain.checker.type.StringType; +import fr.inra.oresing.domain.data.deposit.context.column.Column; import java.util.Map; @@ -17,6 +19,10 @@ public record GroovyValidationCheckResult( ) implements CheckerValidationCheckResult<StringType> { public static GroovyValidationCheckResult success(final CheckerTarget target, final FieldType value) { + if (value instanceof PatternType patternType) { + StringType stringTypeValue = (StringType) patternType.getValue().get(Column.__VALUE__); + return new GroovyValidationCheckResult(ValidationLevel.SUCCESS, null, null, target, stringTypeValue); + } return new GroovyValidationCheckResult(ValidationLevel.SUCCESS, null, null, target, (StringType) value.copy()); } -- GitLab From 171b0e233fa6e1bfdd811b1698eafe3e608e6b4b Mon Sep 17 00:00:00 2001 From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr> Date: Wed, 15 Jan 2025 10:16:49 +0100 Subject: [PATCH 2/5] dans #4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrigé la lecture du groovy et sa verification - le groovy a été modifié - il reste des erreurs non liées à cette anomalie --- .../domain/data/DataColumnPatternValue.java | 15 ++++++++++++++- .../fr/inra/oresing/domain/data/DataDatum.java | 14 +++++++++----- .../GroovyValidationCheckResult.java | 8 +++++++- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java b/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java index 03e38c6..784bd30 100644 --- a/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java +++ b/src/main/java/fr/inra/oresing/domain/data/DataColumnPatternValue.java @@ -3,6 +3,7 @@ package fr.inra.oresing.domain.data; import fr.inra.oresing.domain.application.configuration.Ltree; import fr.inra.oresing.domain.checker.type.*; import fr.inra.oresing.domain.data.deposit.context.DataImporterContext; +import fr.inra.oresing.domain.data.deposit.context.column.Column; import java.util.HashMap; import java.util.Map; @@ -29,7 +30,7 @@ public record DataColumnPatternValue( @Override public DataColumnPatternValue transform(final Function<FieldType, FieldType> transformation) { - + transformation.apply(values().get(new DataColumn(Column.__VALUE__)).getValuesToCheck()); final Map<Ltree, String> transformedValues = null;//Maps.transformValues(values, transformation::apply); return new DataColumnPatternValue((FieldType) null); } @@ -68,4 +69,16 @@ public record DataColumnPatternValue( public void put(DataColumn secondPatternOfColumn, DataColumnValue valueToStoreInDatabase) { values().put(secondPatternOfColumn, valueToStoreInDatabase); } + + public Map<String, Object> toObjectsExposedInGroovyContext() { + Map<String, Object> result = new HashMap<>(); + for (Map.Entry<DataColumn, DataColumnValue> dataColumnDataColumnValueEntry : values.entrySet()) { + final Object valueThatMayBeNull = Optional.ofNullable(dataColumnDataColumnValueEntry.getValue()) + .map(SomethingToBeStoredAsJsonInDatabase::toJsonForDatabase) + .map(Object::toString) + .orElse(null); + result.put(dataColumnDataColumnValueEntry.getKey().toJsonForDatabase(), valueThatMayBeNull); + } + return result; + } } \ No newline at end of file diff --git a/src/main/java/fr/inra/oresing/domain/data/DataDatum.java b/src/main/java/fr/inra/oresing/domain/data/DataDatum.java index cf607d0..f26fec8 100644 --- a/src/main/java/fr/inra/oresing/domain/data/DataDatum.java +++ b/src/main/java/fr/inra/oresing/domain/data/DataDatum.java @@ -122,11 +122,15 @@ public class DataDatum implements SomethingThatCanProvideEvaluationContext, Some public ImmutableMap<String, Object> toObjectsExposedInGroovyContext() { final Map<String, Object> map = new LinkedHashMap<>(); for (final Map.Entry<DataColumn, DataColumnValue> entry : values.entrySet()) { - final Object valueThatMayBeNull = Optional.ofNullable(entry.getValue()) - .map(SomethingToBeStoredAsJsonInDatabase::toJsonForDatabase) - .map(Object::toString) - .orElse(null); - map.put(entry.getKey().toJsonForDatabase(), valueThatMayBeNull); + if (entry.getValue() instanceof DataColumnPatternValue patternValue) { + map.put(entry.getKey().toJsonForDatabase(), patternValue.toObjectsExposedInGroovyContext()); + } else { + final Object valueThatMayBeNull = Optional.ofNullable(entry.getValue()) + .map(SomethingToBeStoredAsJsonInDatabase::toJsonForDatabase) + .map(Object::toString) + .orElse(null); + map.put(entry.getKey().toJsonForDatabase(), valueThatMayBeNull); + } } return ImmutableMap.copyOf(map); } diff --git a/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java b/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java index 3f1a5c5..0ae2f2f 100644 --- a/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java +++ b/src/main/java/fr/inra/oresing/domain/data/deposit/validation/validationcheckresults/GroovyValidationCheckResult.java @@ -9,6 +9,7 @@ import fr.inra.oresing.domain.checker.type.StringType; import fr.inra.oresing.domain.data.deposit.context.column.Column; import java.util.Map; +import java.util.Optional; public record GroovyValidationCheckResult( ValidationLevel level, @@ -20,7 +21,12 @@ public record GroovyValidationCheckResult( public static GroovyValidationCheckResult success(final CheckerTarget target, final FieldType value) { if (value instanceof PatternType patternType) { - StringType stringTypeValue = (StringType) patternType.getValue().get(Column.__VALUE__); + StringType stringTypeValue = Optional.ofNullable(patternType) + .map(PatternType::getValue) + .map(values -> values.get(Column.__VALUE__)) + .map(Object::toString) + .map(StringType::getStringTypeFromStringValue) + .orElse(StringType.getStringTypeFromStringValue("")); return new GroovyValidationCheckResult(ValidationLevel.SUCCESS, null, null, target, stringTypeValue); } return new GroovyValidationCheckResult(ValidationLevel.SUCCESS, null, null, target, (StringType) value.copy()); -- GitLab From 859ba140426c834f6f1ad18060d69d7867771f3b Mon Sep 17 00:00:00 2001 From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr> Date: Thu, 16 Jan 2025 14:35:12 +0100 Subject: [PATCH 3/5] Modification de la documentation --- documentations/openadom/_quarto.yml | 29 ++- documentations/openadom/_variables.yml | 73 +++++- .../openadom/fichiers/autres/database.qmd | 5 +- .../openadom/fichiers/autres/glossaire.qmd | 101 +++++++++ .../configuration_min/description.qmd | 2 +- .../fichiers/fichier_echange/aide_fichier.qmd | 4 +- .../fichiers/fichier_echange/application.qmd | 114 ++++++++++ .../fichier_echange/authorizations.qmd | 7 + .../openadom/fichiers/fichier_echange/data.md | 17 -- .../fichiers/fichier_echange/data.qmd | 207 ++++++++++++++++++ .../data/components/basic_components.qmd | 3 +- .../components/components_description.qmd | 0 .../data/components/computed_components.md | 29 ++- .../data/components/constant_components.md | 16 +- .../data/components/dynamic_components.qmd | 10 +- .../data/components/importHeader.qmd | 0 .../data/components/pattern_components.md | 5 - .../data/components/pattern_components.qmd | 125 +++++++++++ .../{etiquettes.md => etiquettes.qmd} | 21 +- .../fichiers/fichier_echange/submission.qmd | 7 + .../fichiers/fichier_echange/validations.qmd | 8 + .../{verificateurs.md => verificateurs.qmd} | 65 ++++-- .../{yaml.qmd => fichier_csv.qmd} | 31 ++- .../fichiers/introduction/vocabulaire.qmd | 37 +++- .../openadom/img/application-en.png | Bin 0 -> 30041 bytes .../openadom/img/application_fr.png | Bin 0 -> 30402 bytes 26 files changed, 809 insertions(+), 107 deletions(-) create mode 100644 documentations/openadom/fichiers/autres/glossaire.qmd create mode 100644 documentations/openadom/fichiers/fichier_echange/application.qmd create mode 100644 documentations/openadom/fichiers/fichier_echange/authorizations.qmd delete mode 100644 documentations/openadom/fichiers/fichier_echange/data.md create mode 100644 documentations/openadom/fichiers/fichier_echange/data.qmd create mode 100644 documentations/openadom/fichiers/fichier_echange/data/components/components_description.qmd create mode 100644 documentations/openadom/fichiers/fichier_echange/data/components/importHeader.qmd delete mode 100644 documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.md create mode 100644 documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.qmd rename documentations/openadom/fichiers/fichier_echange/{etiquettes.md => etiquettes.qmd} (77%) create mode 100644 documentations/openadom/fichiers/fichier_echange/submission.qmd create mode 100644 documentations/openadom/fichiers/fichier_echange/validations.qmd rename documentations/openadom/fichiers/fichier_echange/{verificateurs.md => verificateurs.qmd} (84%) rename documentations/openadom/fichiers/introduction/{yaml.qmd => fichier_csv.qmd} (50%) create mode 100644 documentations/openadom/img/application-en.png create mode 100644 documentations/openadom/img/application_fr.png diff --git a/documentations/openadom/_quarto.yml b/documentations/openadom/_quarto.yml index 2ffb8ae..02c9dc2 100644 --- a/documentations/openadom/_quarto.yml +++ b/documentations/openadom/_quarto.yml @@ -31,15 +31,17 @@ website: - text: Vocabulaire href: fichiers/introduction/vocabulaire.qmd - text: Fichier d'échange - href: fichiers/introduction/yaml.qmd + href: fichiers/introduction/fichier_csv.qmd - section: Fichiers d'échange contents: - - text: Données - href: fichiers/fichier_echange/data.md - text: Aide fichier href: fichiers/fichier_echange/aide_fichier.qmd + - text: Application (OA_application) + href: fichiers/fichier_echange/application.qmd + - text: Données + href: fichiers/fichier_echange/data.qmd - text: Etiquettes - href: fichiers/fichier_echange/etiquettes.md + href: fichiers/fichier_echange/etiquettes.qmd - section: Components contents: - text: Basic Components @@ -49,11 +51,24 @@ website: - text: Dynamic Components href: fichiers/fichier_echange/data/components/dynamic_components.qmd - text: Constant Components - href: /fichiers/fichier_echange/data/components/constant_components.md + href: fichiers/fichier_echange/data/components/constant_components.md - text: Pattern Components - href: fichiers/fichier_echange/data/components/pattern_components.md + href: fichiers/fichier_echange/data/components/pattern_components.qmd + - section: + text: Paramétrage des composants + href: fichiers/fichier_echange/data/components/components_description.qmd + contents: + - text: Etiquettes (OA_tags) + href: fichiers/fichier_echange/etiquettes.qmd + - text: Verificateurs - href: fichiers/fichier_echange/verificateurs.md + href: fichiers/fichier_echange/verificateurs.qmd + - text: Validations + href: fichiers/fichier_echange/validations.qmd + - text: Dépôt de fichier (OA_submission) + href: fichiers/fichier_echange/submission.qmd + - text: Autorisations (OA_autorisations) + href: fichiers/fichier_echange/authorizations.qmd - section: Pour aller plus loin contents: - text: Authorization diff --git a/documentations/openadom/_variables.yml b/documentations/openadom/_variables.yml index 354d3bf..898c738 100644 --- a/documentations/openadom/_variables.yml +++ b/documentations/openadom/_variables.yml @@ -37,50 +37,101 @@ page-refs: link-nk: "[clef naturelle](/fichiers/introduction/vocabulaire.qmd#clef-naturelle)" link-hk: "[clef hierarchique](/fichiers/introduction/vocabulaire.qmd#clef-hierarchique)" link-data: "[données](/fichiers/introduction/vocabulaire.qmd#referentiels)" - yaml: - href: /fichiers/introduction/yaml.qmd + link-identificateurs: "[Identificateurs](/fichiers/introduction/vocabulaire.qmd#identificateurs)" + csv: + href: /fichiers/introduction/fichier_csv.qmd text: Fichier d'échange - link: "[Fichier d'échange](/fichiers/introduction/yaml.qmd)" + link: "[Fichier d'échange](/fichiers/introduction/fichier_csv.qmd)" # Section Fichiers d'échange + application: + href: /fichiers/fichier_echange/application.qmd + text: Application (OA_application) + link: "[Application (OA_application)](/fichiers/fichier_echange/application.qmd)" + oa: "[OA_application](/fichiers/fichier_echange/application.qmd)" + oa-name: "[OA_application](/fichiers/fichier_echange/application.qmd#name)" + oa-version: "[OA_application](/fichiers/fichier_echange/application.qmd#version)" + oa-defaultLanguage: "[OA_application](/fichiers/fichier_echange/application.qmd#defaultLanguage)" + oa-comment: "[OA_application](/fichiers/fichier_echange/application.qmd#comment)" + oa-i18n: "[OA_i18n](/fichiers/fichier_echange/application.qmd#i18n)" data: - href: /fichiers/fichier_echange/data.md + href: /fichiers/fichier_echange/data.qmd text: Données - link: "[Données](/fichiers/fichier_echange/data.md)" + link: "[Données](/fichiers/fichier_echange/data.qmd)" + oa: "[OA_data](/fichiers/fichier_echange/data.qmd)" + oa-nk: "[OA_naturalKey](/fichiers/fichier_echange/data.qmd#nk)" + oa-i18n: "[OA_i18n](/fichiers/fichier_echange/data.qmd#i18n)" + oa-displayPattern: "[OA_i18nDisplayPattern](/fichiers/fichier_echange/data.qmd#displayPattern)" + oa-components: "[Components](/fichiers/fichier_echange/data.qmd#components)" + oa-headerLine: "[OA_DATA_HEADER_LINE](/fichiers/fichier_echange/data.qmd#headerLine)" + oa-firstLine: "[OA_DATA_FIRST_LINE](/fichiers/fichier_echange/data.qmd#firstLine)" + oa-unexpectedColumns: "[OA_ALLOW_UNEXPECTED_COLUMNS](/fichiers/fichier_echange/data.qmd#unexpectedColumns)" + oa-separator: "[OA_separator](/fichiers/fichier_echange/data.qmd#separator)" + oa-validations: "[OA_separator](/fichiers/fichier_echange/data.qmd#validations)" + authorizations: + href: /fichiers/fichier_echange/submission.qmd + text: Définition des composantes participant à la construction d'autorisations. + link: "[Authorizations](/fichiers/fichier_echange/authorizations.qmd)" + oa: "[OA_authorizations](/fichiers/fichier_echange/authorizations.qmd)" + submission: + href: /fichiers/fichier_echange/submission.qmd + text: Stratégie de dépôt + link: "[Stratégie de dépôt](/fichiers/fichier_echange/submission.qmd)" + oa: "[OA_submission](/fichiers/fichier_echange/submission.qmd)" + validations: + href: /fichiers/fichier_echange/validations.qmd + text: Règles de validations + link: "[Règles de validations](/fichiers/fichier_echange/validations.qmd)" + oa: "[OA_validations](/fichiers/fichier_echange/validations.qmd)" aide-fichier: href: /fichiers/fichier_echange/aide_fichier.qmd text: Aide fichier link: "[Aide fichier](/fichiers/fichier_echange/aide_fichier.qmd)" + oa-version: "[OA_validations](/fichiers/fichier_echange/aide_fichier.qmd#openadom_version)" etiquettes: - href: /fichiers/fichier_echange/etiquettes.md + href: /fichiers/fichier_echange/etiquettes.qmd text: Etiquettes - link: "[Etiquettes](/fichiers/fichier_echange/etiquettes.md)" + link: "[Etiquettes](/fichiers/fichier_echange/etiquettes.qmd)" + oa: "[OA_tags](/fichiers/fichier_echange/etiquettes.qmd)" # Components + desc-comp: + href: /home/ptcherniati/projets/backend/documentations/openadom/fichiers/fichier_echange/data/components/components_description.qmd + text: "Description des \"components\"" + link: "[Description des \"components\"](/home/ptcherniati/projets/backend/documentations/openadom/fichiers/fichier_echange/data/components/components_description.qmd)" + basic-comp: href: /fichiers/fichier_echange/data/components/basic_components.qmd text: Basic Components link: "[Basic Components](/fichiers/fichier_echange/data/components/basic_components.qmd)" + oa: "[OA_basicComponents](/fichiers/fichier_echange/data/components/basic_components.qmd)" computed-comp: href: /fichiers/fichier_echange/data/components/computed_components.md text: Computed Components link: "[Computed Components](/fichiers/fichier_echange/data/components/computed_components.md)" + oa: "[OA_computedComponents](/fichiers/fichier_echange/data/components/computed_components.md)" dynamic-comp: href: /fichiers/fichier_echange/data/components/dynamic_components.qmd text: Dynamic Components link: "[Dynamic Components](/fichiers/fichier_echange/data/components/dynamic_components.qmd)" + oa: "[OA_dynamicComponents](/fichiers/fichier_echange/data/components/dynamic_components.qmd)" constant-comp: href: /fichiers/fichier_echange/data/components/constant_components.md text: Constant Components link: "[Constant Components](/fichiers/fichier_echange/data/components/constant_components.md)" + oa: "[OA_constantComponents](/fichiers/fichier_echange/data/components/constant_components.md)" pattern-comp: - href: /fichiers/fichier_echange/data/components/pattern_components.md + href: /fichiers/fichier_echange/data/components/pattern_components.qmd text: Pattern Components - link: "[Pattern Components](/fichiers/fichier_echange/data/components/pattern_components.md)" + link: "[Pattern Components](/fichiers/fichier_echange/data/components/pattern_components.qmd)" checker: - href: /fichiers/fichier_echange/verificateurs.md + href: /fichiers/fichier_echange/verificateurs.qmd text: Vérificateurs (OA_checker) - link: "[Vérificateurs (OA_checker)](/fichiers/fichier_echange/verificateurs.md)" + link: "[Vérificateurs (OA_checker)](/fichiers/fichier_echange/verificateurs.qmd)" + link-multiplicity: "[Multiplicity (OA_multiplicity)](/fichiers/fichier_echange/verificateurs.qmd#multiplicity)" + oa-multiplicity: "[OA_multiplicity](/fichiers/fichier_echange/verificateurs.qmd#multiplicity)" + link-numericchecker: "[Vérificateur de type 'Integer' et 'Float'](/fichiers/fichier_echange/verificateurs.qmd#numericchecker)" + oa: "[OA_checker](/fichiers/fichier_echange/verificateurs.qmd)" # section pour aller plus loin authorization: text: Authorization diff --git a/documentations/openadom/fichiers/autres/database.qmd b/documentations/openadom/fichiers/autres/database.qmd index bee0dee..655d736 100644 --- a/documentations/openadom/fichiers/autres/database.qmd +++ b/documentations/openadom/fichiers/autres/database.qmd @@ -35,10 +35,9 @@ quatre roles sont créés : - **public** : ce rôle porte les droits en lecture des données des différents SI. Tout utilisateur d'openadom est placé dans cce rôle. ̀̀̀ -``` -â— +:::{.callout-warning} Un applicationCreator ne peut pas accéder aux application, ni les modifier. S'il créé une application il deviendra administrateur de cette application. S'il ne l'a pas créer, ces droits sur le SI dependront des administrateurs de cette application. -``` +::: Après le démarrage, il convient de créer les utilisateurs qui pourront permettre la création du SI. diff --git a/documentations/openadom/fichiers/autres/glossaire.qmd b/documentations/openadom/fichiers/autres/glossaire.qmd new file mode 100644 index 0000000..299f0d3 --- /dev/null +++ b/documentations/openadom/fichiers/autres/glossaire.qmd @@ -0,0 +1,101 @@ +--- + title: Glossaire + abstract: Cette section reprend tout les mots clefs pré-définis du fichier de configuration +--- +# Sections OpenAdom +## {{<var page-refs.checker.oa>}} + Les vérificateurs permettent de valider et de typer les différents composants +## OA_DEFAULT_VALUE +## {{<var page-refs.data.oa-unexpectedColumns>}} +## OA_HEADER_NAME +## {{<var page-refs.etiquettes.oa>}} + Les étiquettes permettent de regrouper certains éléments (data, components) +## OA_REQUIRED +## OA_IMPORT_HEADER +## OA_IMPORT_HEADER_PATTERN +## OA_I_18_N +voir {{<var page-refs.i18n.link>}} + - pour l'application {{<var page-refs.application.oa-i18n>}} + - pour un type de données {{<var page-refs.data.oa-i18n>}} +## {{<var page-refs.data.oa-displayPattern>}} +## OA_TITLE +## OA_LANG_RESTRICTIONS +## OA_FORM_FIELDS +## OA_MIN +## OA_DURATION +## OA_PATTERN +## OA_MAX +## OA_NAME + Peut définir le nom de l'application ({{<var page-refs.application.oa-name>}}) +## OA_EXPRESSION +## OA_GROOVY_EXCEPTIONS +## OA_ADDITIONAL_FILES +## {{<var page-refs.application.oa>}} + Cette section permet de renseigner les informations et paramétrage de l'application. +## {{<var page-refs.authorizations.oa>}} +## OA_AUTHORIZATION_SCOPES +## {{<var page-refs.basic-comp.oa>}} + Les composantes basiques permettent de capturer les colonnes du fichier en entrée. +## {{<var page-refs.application.oa-comment>}} + Un commentaire libre pour le fichier de configuration +## OA_COMPONENT +## OA_COMPONENTS +## OA_COMPONENT_ADJACENTS +## OA_COMPONENT_QUALIFIERS +## OA_COMPUTATION +## {{<var page-refs.computed-comp.oa>}} + Les composantes calculées pemettent de créer de nouvelles composantes en utilisant une expression groovy. +## {{<var page-refs.constant-comp.oa>}} + Les composantes constantes pemettent de créer des constantes pour l'ensemble du fichier provenant généralement de l'en-tête du fichier ou des lignes entre l'en-tête et la première ligne de data. +## OA_CONSTANT_IMPORT_HEADER_COLUMN_NAME +## OA_CONSTANT_IMPORT_HEADER_COLUMN_NUMBER +## OA_CONSTANT_IMPORT_HEADER_ROW_NUMBER +## OA_CONSTANT_IMPORT_HEADER_TARGET +## {{<var page-refs.data.oa>}} + La section data permet de définir les types de données du domaine +## OA_DATA_FIRST_LINE +## OA_DATA_HEADER_LINE +## {{<var page-refs.application.oa-defaultLanguage>}} + Pour l'ensemble de l'application, la langue par défaut. +## OA_DESCRIPTION +## {{<var page-refs.dynamic-comp.oa>}} + Les composantes dynamiques permettent de déclarer des colonnes dont les nom sont construit sur le contenu d'une composante d'un référentiel. +## OA_END_DATE_MATCH_PATTERN +## OA_EXPORT_HEADER +## OA_FILE_NAME +## OA_FILE_PATTERN +## {{<var page-refs.data.oa-firstLine>}} +## OA_GROOVY +## {{<var page-refs.data.oa-headerLine>}} +## OA_HEADER_PREFIX +## OA_IS_PARENT +## OA_IS_RECURSIVE +## OA_IS_TRUE +## OA_MANDATORY +## OA_MATCH_PATTERN_SCOPES +## {{<var page-refs.checker.oa-multiplicity>}} + Permet de déclarer si une données est un tableau de valeur. +## {{<var page-refs.data.oa-nk>}} +## OA_PARAMS +## {{<var page-refs.pattern-comp.oa>}} + Les composantes pattern permettent de lire les données de colonnes répondant à une expression régulière. + + En plus : + - on peut extraire des données du nom de la colonne + - on peut définir et capturer les données de colonnes adjacentes + - le résultat est veritcalisé (les colonnes capturés sont enregistrées comme des lignes différentes) +## OA_PATTERN_FOR_COMPONENTS +## OA_REFERENCE +## OA_REFERENCES +## OA_REFERENCE_COMPONENT_TO_LOOK_FOR_HEADER +## OA_REFERENCE_SCOPES +## OA_RIGHTS_REQUEST +## {{<var page-refs.data.oa-separator>}} +## OA_START_DATE_MATCH_PATTERN +## OA_STRATEGY +## {{<var page-refs.validations.oa>}} +## OA_SUBMISSION_SCOPE +## OA_TIME_SCOPE +## {{<var page-refs.validations.oa>}} +## OA_VERSION + utilisé pour définir la version {{<page-refs.aide_fichier.oa-version>}} du moteur OpenADOM comme pour définir la version {{<page-refs.application.oa-version>}} du fichier de configuration de l'application. \ No newline at end of file diff --git a/documentations/openadom/fichiers/examples/configuration_min/description.qmd b/documentations/openadom/fichiers/examples/configuration_min/description.qmd index d688aeb..4f75f49 100644 --- a/documentations/openadom/fichiers/examples/configuration_min/description.qmd +++ b/documentations/openadom/fichiers/examples/configuration_min/description.qmd @@ -2,7 +2,7 @@ Un fichier de configuration doit au moins contenir la version du moteur openADom (OA_version), ainsi que la description de l'application (OA_application) -- le nom de l'aapplication respectant le pattern <code>[a-z_]*</code> +- le nom de l'application respectant le pattern <code>[a-z_]*</code> - la version de l'application <code>(^(\\d+)\\.(\\d+)\.(\\d+)(_\\d+)?(-\\w+)?$)</code> diff --git a/documentations/openadom/fichiers/fichier_echange/aide_fichier.qmd b/documentations/openadom/fichiers/fichier_echange/aide_fichier.qmd index 033fbcd..741cd6d 100644 --- a/documentations/openadom/fichiers/fichier_echange/aide_fichier.qmd +++ b/documentations/openadom/fichiers/fichier_echange/aide_fichier.qmd @@ -26,8 +26,8 @@ soit valide. Il y a 6 parties (<span style="color: orange">sans indentation</span>) attendues dans le fichier : -* OA_version, -* [OA_application](#application), +* OA_version [#openadom_version], +* {{<var page-refs.application.link>}}, * [OA_data](#data), * [OA_tags](#tags), * [OA_additionalFiles](#additionalFiles) diff --git a/documentations/openadom/fichiers/fichier_echange/application.qmd b/documentations/openadom/fichiers/fichier_echange/application.qmd new file mode 100644 index 0000000..16d3154 --- /dev/null +++ b/documentations/openadom/fichiers/fichier_echange/application.qmd @@ -0,0 +1,114 @@ +--- +title: Section de description de l'application +subtitle: OA_application +abstract: > + Cette section définit un certain nombre d'informations et de paramètres de l'ensemble du système d'information +lightbox: + match: auto + effect: fade + desc-position: left + loop: false +--- + +# Déclaration d'une donnée + +``` yaml +OA_data: + tr_donnee_de_reference_ddr: + ... + t_donne_dat: + ... +``` +::: {.callout-caution} +Pour déclarer une donnée vous devez fournir un identificateur + + +::: {.callout-note title="example de section application" collapse="false"} +``` yaml +OA_application: + OA_defaultLanguage: fr + OA_i18n: + OA_title: + fr: "ACBB" + en: "ACBB" + OA_description: + fr: "Agroécosystèmes, Cycles Biogéochimiques et Biodiversité" + en: "Agroecosystems, Biogeochemical Cycles and Biodiversity" + OA_comment: "L'application ACBB V2" + OA_name: acbb_openadom_v2 + OA_version: 1.0.5 +``` + +::: + +Cette section doit comporter obligatoirement: + +(@) [**OA_name**](#name) le nom de l'application qui correspondra au nom du schema de la base de données. + + ``` yaml + OA_name: acbb_openadom_v2 + ``` + +Ce nom doit obligatoirement -etre en minuscules, commencer par une lettre et ne comporter que des caractères alphanumériques sans accent et l'espace souligné. (_) + +(@) [**OA_version**](#version) qui correspond à la version du fichier de configuration. Lors des mise à jour du schéma, vous incrémenterez ce numéro de version. + + ``` yaml + OA_version: 1.0.5 + ``` + +::: {.callout-note collapse="true" title="Exemple de numérotation" } + +### Versions Majeures + +- 2.4.0 +- 2.4.1 +- 2.3.5 +- 2.0.0 +- 3.0.0 +- 1.11.2 +- 1.10.0 +- 1.9.0 + +### Versions de Développement + +- 2.4.0-SNAPSHOT +- 2.3.5-SNAPSHOT +- 2.0.0-rc.3 +- 2.0.0-b.2 +- 2.0.0-a.1 + +### Versions avec Métadonnées +- 1.2.3+20231006 +- 1.2.0+build.123 + +### Versions de Maintenance +- 1.2.5 +- 1.2.3 +::: + +On peut aussi rajouter des informations facultatives: + +1. [**OA_defaultLanguage**](#defaultLanguage) qui permet de définir la langue par défaut. La langue par défaut est celle utilisée si aucune autre information de langue n'est précisée. Lors de l'internationalisation de certains champs / données, on essait de trouver la traduction dans la langue demandée; à défaut on fournit la traduction dans la langue par défaut; si aucune traduction n'est trouvée on renvoit l'indentificateur fourni en entrée. + + ``` yaml + OA_defaultLanguage: fr + ``` + + 2. **[OA_i18n]{i18n}** cette section permet d'internationaliser le nom de l'application en fournissant un titre et / ou une description à ce nom. + +``` yaml + OA_i18n: + OA_title: + fr: "ACBB" + en: "ACBB" + OA_description: + fr: "Agroécosystèmes, Cycles Biogéochimiques et Biodiversité" + en: "Agroecosystems, Biogeochemical Cycles and +``` + +{height="100" .lightbox} + +{height="100" .lightbox} + +3. [**OA_comment** ](#comment) C'est un commentaire, que vous pouvez remplir à votre guise pour vous permettre d'indiquer les modifications de version en version. \ No newline at end of file diff --git a/documentations/openadom/fichiers/fichier_echange/authorizations.qmd b/documentations/openadom/fichiers/fichier_echange/authorizations.qmd new file mode 100644 index 0000000..b988b85 --- /dev/null +++ b/documentations/openadom/fichiers/fichier_echange/authorizations.qmd @@ -0,0 +1,7 @@ +--- +title: Autorisations +subtitle: OA_authorizations +abstract: > + Cette section permet de déclarer les composantes intervenant dans les autorizations. +--- +TODO \ No newline at end of file diff --git a/documentations/openadom/fichiers/fichier_echange/data.md b/documentations/openadom/fichiers/fichier_echange/data.md deleted file mode 100644 index a036794..0000000 --- a/documentations/openadom/fichiers/fichier_echange/data.md +++ /dev/null @@ -1,17 +0,0 @@ -### <a id="data" />Description des données (OA_Data) - -On décrit les données de références et les types de données dans la partie *OA_data*, on y liste les noms des colonnes souhaitées (dans {{< var page-refs.basic-comp.link >}}, {{< var page-refs.computed-comp.link >}}, {{< var page-refs.pattern-comp.link >}}, {{< var page-refs.pattern-comp.link >}}, {{< var page-refs.constant-comp.link >}};en précisant la liste des colonnes qui forme la {{< var page-refs.vocab.link-nk >}}. - -Pour ajouter une référence, on ajoute dans la section "*OA_data*" une description de ce référentiel. - -- un {{< var page-refs.basic-comp.link >}} - est une colonne du fichier, -- un {{< var page-refs.computed-comp.link >}} - est une colonne qui n’est pas présente dans le fichier et dont la valeur est une constante ou le résultat d'un calcul, -- un {{< var page-refs.dynamic-comp.link >}} - est un ensemble de colonnes dont la clef est la concaténation d'un préfixe et d'une valeur d'un référentiel. Par exemple s’il existe un référentiel "propriétés" avec les valeurs (couleur, catégorie, obligatoire), on pourrait avoir dans un autre référentiel (en utilisant le préfixe "pts_") pts_couleur, pts_catégorie et pts_obligatoire, en les déclarant comme {{< var page-refs.dynamic-comp.link >}} -, -- un {{< var page-refs.pattern-comp.link >}} - est un ensemble de colonnes dont le nom à un format commun et qui par conséquent répond à un pattern. Par exemple avec des colonnes dont le nom répond au pattern variable_profondeur_répétition : SWC_([0-9]*)_([0-9]*), -- un {{< var page-refs.constant-comp.link >}} est le descriptif de la cartouche du fichier csv. On précisera le nombre de lignes dans la cartouche dans rowNumber et le nombre de colonnes utiliser dans la cartouche dans columnNumber. On peut aussi choisir pour des informations sous l’en-tête de préciser le nom de l’en-tête headerName en lieu et place du numéro de colonne. - diff --git a/documentations/openadom/fichiers/fichier_echange/data.qmd b/documentations/openadom/fichiers/fichier_echange/data.qmd new file mode 100644 index 0000000..d4eba92 --- /dev/null +++ b/documentations/openadom/fichiers/fichier_echange/data.qmd @@ -0,0 +1,207 @@ +--- + title: Description des données + subtitle: OA_Data + abstract: > + <p>Cette section permet de décrire vos données en les regroupant par type de données. + <p>Pour chaque tye de données on va décrire les données que l'on souhaite enregistrer et les modalités de dépôt et d'extraction de ces données. +--- + +# Types de données + +On appelera type de données un regroupement de données (variables) qui partage une même thématique et pouvant partager un modèle de {{<var page-refs.csv.link>}} commun. + +Les types de données sont alimentés dans la base par des fichier au format csv. + +On définit aussi des données dites de références. Ce sont des données nécessaires à la description des données expérimentales (référentiels) ou d'observation (data). Il n'y a pas de différence dans l'application pour le traitement des référentiels et des data. Les seules différences se retrouvent dans la présentation au niveau de l'interface. Pour définir un type de données "data", on ajoute dans la section {{<var page-refs.etiquettes.oa>}} un tag **__DATA__**. + +On décrit les données de références et les types de données dans la partie *OA_data*, on y liste les noms des colonnes souhaitées (dans {{< var page-refs.basic-comp.link >}}, {{< var page-refs.pattern-comp.link >}} et {{< var page-refs.pattern-comp.link >}}, des constantes extraites du cartouche {{< var page-refs.constant-comp.link >}} et des valeurs calculées {{< var page-refs.computed-comp.link >}} + +Pour ajouter une référence, on ajoute dans la section "*OA_data*" une description de ce référentiel. + +## Déclaration d'un type de données +Chaque type de donnée aura une entrée dans la section OA_data en utilisant les {{<var page-refs.vocab.link-identificateurs>}} + +::: {.callout-note title="déclaration du type de données tr_sites_sit" collapse="false"} +``` yaml +OA_data: + tr_sites_site: + .... +``` +::: + +## Clef naturelle ([OA_naturalKey]{#nk}) +Vous devrez déclarer une {{< var page-refs.vocab.link-nk >}}. + +::: {.callout-note title="OA_naturalKey" collapse="false"} +``` yaml +OA_data: + tr_sites_site: + OA_naturalKey: [sit_site_key] +``` +ou si vous préférez la notation en colonne + +``` yaml +OA_data: + tr_sites_site: + OA_naturalKey: + - sit_site_key +``` +::: + +## Internationalisation ([OA_i18n]{#i18n}) +Vous pouvez internationaliser votre type de données en rajoutant une section **OA_i18n** voir la section {{< var page-refs.i18n.link >}}. + +::: {.callout-note title="OA_i18n" collapse="false"} +``` yaml + +OA_data: + tr_sites_site: + OA_i18n: + OA_title: + fr: référence aux sites + en: reference to sites + OA_description: + fr: sites d'etudes + en: study sites +``` +::: + +## Surcharge de la clef naturelle lors du référencement ([OA_i18nDisplayPattern]{#displayPattern}) +Lorsque dans un autre type de données vous ferez référence un ce tye de données, c'est la clef naturelle de la ligne référencée qui s'affichera. + +Vous pourrez surcharger cet affichage en déclarant un pattern d'affichage en utilisant les valeurs de la ligne référencée dans une section [**OA_i18nDisplayPattern**]{#displayPattern}. + +::: {.callout-note title="OA_i18nDisplayPattern" collapse="false"} +``` yaml + +OA_data: + tr_sites_site: + OA_i18nDisplayPattern: #mandatory + OA_title: + fr: "{sit_site_fr} dans ({sit_agroecosystem})" + en: "{sit_site_en} in ({sit_agroecosystem})" + +``` +Ici {sit_site_fr} repésente la valeur de la colonne sit_site_fr et {sit_agroecosystem} la valeur de la colonne sit_agroecosystem. + +Si une colonne est aussi une référence, alors récursivement on calculera les inférences de OA_i18nDisplayPattern de tous ces référentiels. +::: + + + +::: {.callout-warning title="Calcul de la valeur d'affichage d'une données" collapse="false"} +Les inférences de OA_i18nDisplayPattern sont calculées au moment du dépôt de la données et stockées en base de données. S'il vous arrivait de modifier les colonnes de référentiels intervenant dans cette construction, alors vous devriez redéposer vos données pour recalculer les valeurs d'affichage. +::: + + + +## Déclaration d'un cartouche + +Par défaut la ligne 1 est la ligne d'en-tête et la ligne 2 celle de la première ligne de données. + +On peut changer ce comportement en précisant : +- [OA_DATA_HEADER_LINE]{#headerLine} la ligne d'en-tête +- [OA_DATA_FIRST_LINE]{#firstLine} la ligne d'en-tête + +::: {.callout-note title="en-tête" collapse="false"} +``` yaml + +OA_data: + tr_sites_site: + OA_DATA_HEADER_LINE: 1 + OA_DATA_FIRST_LINE: 2 +``` +::: + +## Colonnes non signifiantes ([OA_ALLOW_UNEXPECTED_COLUMNS]{#unexpectedColumns}) + +Par défaut, toutes les colonnes présentes dans le fichier de données doivent avoir été déclarées. + +Vous pouvez cependant modifier ce comportement en précisant OA_ALLOW_UNEXPECTED_COLUMNS à true + +::: {.callout-note title="OA_ALLOW_UNEXPECTED_COLUMNS" collapse="false"} +``` yaml + +OA_data: + tr_sites_site: + OA_ALLOW_UNEXPECTED_COLUMNS: true # défaut à false +``` +::: + +## Séparateur de champ [OA_separator]{#separator} +Par défaut le séparateur dans le fichier csv est le point-virgule (;). +Vous pouvez changer ce séparateur en précisant OA_separator + +::: {.callout-note title="OA_separator" collapse="false"} +``` yaml + +OA_data: + tr_sites_site: + OA_separator: , # défaut à ; +``` +::: + +## Etiquettes ([OA_tags]{#tags}) +Vous pouvez étiquetter vos types de données voir {{<var page-refs.etiquettes.oa>}} +- soit pour pouvoir les filtrer dans l'interface +- soit pour ajouter un comportement +-> __DATA__ signifie que ce type de données est une données expérimentale ou d'observation. +-> __ORDER_4__ donne un numéro d'ordre dan l'affichage des types de données. + + +::: {.callout-note title="OA_separator" collapse="false"} +``` yaml + +OA_data: + tr_sites_site: + OA_tags , [semi_horaire, flux, __REFERENCES__, __ORDER_2__] ; +``` +::: + +## Déclaration des [composantes du type de données]{#components} + +- un {{< var page-refs.basic-comp.link >}} est une colonne du fichier, +- un {{< var page-refs.computed-comp.link >}} est une colonne qui n’est pas présente dans le fichier et dont la valeur est une constante ou le résultat d'un calcul, +- un {{< var page-refs.dynamic-comp.link >}} est un ensemble de colonnes dont la clef est la concaténation d'un préfixe et d'une valeur d'un référentiel. Par exemple s’il existe un référentiel "propriétés" avec les valeurs (couleur, catégorie, obligatoire), on pourrait avoir dans un autre référentiel (en utilisant le préfixe "pts_") pts_couleur, pts_catégorie et pts_obligatoire, en les déclarant comme {{< var page-refs.dynamic-comp.link >}} +- un {{< var page-refs.pattern-comp.link >}} est un ensemble de colonnes dont le nom à un format commun et qui par conséquent répond à un pattern. Par exemple avec des colonnes dont le nom répond au pattern variable_profondeur_répétition : SWC_([0-9]*)_([0-9]*), +- un {{< var page-refs.constant-comp.link >}} est le descriptif de la cartouche du fichier csv. On précisera le nombre de lignes dans la cartouche dans rowNumber et le nombre de colonnes utiliser dans la cartouche dans columnNumber. On peut aussi choisir pour des informations sous l’en-tête de préciser le nom de l’en-tête headerName en lieu et place du numéro de colonne. + +## Validation [OA_validations]{#validations} + +Chaque composante peut contenir un vérificateur. Pour la lisibilité, il est conseiller de laisser ces vérificateurs dans la section du composant. Cependant vous pourriez vouloir croiser des informations pour effectuer une validation, ou valider un ensemble de composants de la même façon. + +En ce cas vous serez ammener à définir un certain nombre de règle dans la section + +::: {.callout-note title="OA_validations" collapse="false"} +``` yaml + +OA_data: + tr_sites_site: + OA_validations: + sit_checkDateMiseEnService: + OA_i18n: + fr: "validation de date" + OA_checker: + OA_name: OA_date + OA_params: + OA_pattern : "dd/MM/yyyy" + OA_components: [ sit_date_mise_en_service ] +``` +::: + +## {{<var page-refs.authorizations.text>}} +Cette section vous permet de définir les composantes qui permettront de construire des autorisations voir {{<var page-refs.authorizations.link>}} + + +::: {.callout-note title="OA_validations" collapse="false"} +``` yaml + +OA_data: + t_piegeage_en_montee_pem: + OA_authorizations: + OA_authorizationScope: + - projet + - chemin + OA_timeScope: date +``` +::: \ No newline at end of file diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/basic_components.qmd b/documentations/openadom/fichiers/fichier_echange/data/components/basic_components.qmd index d363a31..bdf53a5 100644 --- a/documentations/openadom/fichiers/fichier_echange/data/components/basic_components.qmd +++ b/documentations/openadom/fichiers/fichier_echange/data/components/basic_components.qmd @@ -1,5 +1,6 @@ --- - title: Description des colonnes (OA_basicComponents) + title: Description des colonnes + subtitle: (OA_basicComponents) abstract: Ce document permet de configurer la section <b>OA_data > OA_basiComponents</b> pour lier les colonnes du fichier à des composantes --- diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/components_description.qmd b/documentations/openadom/fichiers/fichier_echange/data/components/components_description.qmd new file mode 100644 index 0000000..e69de29 diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/computed_components.md b/documentations/openadom/fichiers/fichier_echange/data/components/computed_components.md index db26d19..1a8e5fc 100644 --- a/documentations/openadom/fichiers/fichier_echange/data/components/computed_components.md +++ b/documentations/openadom/fichiers/fichier_echange/data/components/computed_components.md @@ -1,7 +1,16 @@ +--- + title: Colonnes calculées + subtitle: OA_computedComponents + abstract: > + Une colonne calculée est une colonne qui n'est pas présente dans le fichier. Ses valeurs sont issues du résultat d'un calcul ou d'une concaténation. +--- +Par exemple on veut avoir la valeur de la date complète en concaténant la date (tds_date) et l'heure (tds_heure). -#### <a id="computedComponents" />Colonnes calculées (OA_computedComponents) +Dans l'{{< var page-refs.groovy.link >}}, les valeurs sont dans une map datum : +- datum.tds_date +- datum.tds_heure -Une colonne calculée est une colonne qui n'est pas présente dans le fichier. Ses valeurs sont issues du résultat d'un calcul ou d'une concaténation. +On définit dans le fichier de configuration la section OA_data suivante: ```yaml OA_data: @@ -12,12 +21,24 @@ OA_data: - tds_nom OA_basicComponents: tds_nom: - OA_importHeader: nom + OA_importHeader: Nom + tds_date: + OA_importHeader: Date + OA_checker: + OA_name: OA_date + OA_params: + OA_pattern: dd/MM/yyyy + tds_heure: + OA_importHeader: Heure + OA_checker: + OA_name: OA_date + OA_params: + OA_pattern: HH:mm:ss OA_computedComponents: tds_date_heure: OA_computation: OA_expression: > - return datum.date + " " + datum.heure + return datum.tds_date + " " + datum.tds_heure OA_checker: OA_name: OA_date OA_params: diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/constant_components.md b/documentations/openadom/fichiers/fichier_echange/data/components/constant_components.md index ebc94e6..4962f8d 100644 --- a/documentations/openadom/fichiers/fichier_echange/data/components/constant_components.md +++ b/documentations/openadom/fichiers/fichier_echange/data/components/constant_components.md @@ -1,18 +1,20 @@ - -#### <a id="constantComponents" />Constantes du csv (OA_constantComponents) - -Les constantes permettent de déclarer les données enregistrées dans les cartouches du fichier csv. +--- + title: Constantes du csv + subtitl: OA_constantComponents + abstract: > + Les constantes permettent de déclarer les données enregistrées dans les cartouches du fichier csv. +--- Pour le fichier : __flux_journalier.csv__ ``` - ************* Début de la cartouche ************** + ************* Début du cartouche ************** 1| Site | Hesse | 2| Theme | flux | 3| Frequence | journalier | 4| Date de debut | 01/01/2008 | 5| Date de fin | 05/01/2008 | 6| Commentaire | un commentaire | - ************** Fin de la cartouche *************** + ************** Fin du cartouche *************** 7| | | | 8| Date | Carbon dioxide concentration | Water vapour concentration | |---------------|--------------------------------|----------------------------| @@ -22,7 +24,7 @@ Pour le fichier : __flux_journalier.csv__ 12| 02/01/2008 | 418,4319752083 | 3,6077222917 | ``` -On définira le yaml suivant : +On définira dans le fichier de configuration la section suivante : ```yaml OA_data: diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/dynamic_components.qmd b/documentations/openadom/fichiers/fichier_echange/data/components/dynamic_components.qmd index 8df1a99..ee058d7 100644 --- a/documentations/openadom/fichiers/fichier_echange/data/components/dynamic_components.qmd +++ b/documentations/openadom/fichiers/fichier_echange/data/components/dynamic_components.qmd @@ -1,7 +1,9 @@ - -#### <a id="dynamicComponents" />Colonnes dynamiques (OA_dynamicComponents) - -Les colonnes dynamiques permettent de traduire une relation n-n entre deux référentiels. Par exemple entre un objet et ses propriétés. +--- + title: Colonnes dynamiques + subtitle: OA_dynamicComponents + abstract: > + Les colonnes dynamiques permettent de traduire une relation n-n entre deux référentiels. Par exemple entre un objet et ses propriétés. +--- ``` {mermaid} classDiagram Taxon "*" -- "*" Proprietes_de_taxon diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/importHeader.qmd b/documentations/openadom/fichiers/fichier_echange/data/components/importHeader.qmd new file mode 100644 index 0000000..e69de29 diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.md b/documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.md deleted file mode 100644 index ffcc568..0000000 --- a/documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.md +++ /dev/null @@ -1,5 +0,0 @@ -#### <a id="patternComponents" />Colonnes avec pattern (OA_patternComponents) - -Verticalisation qui parse selon une regexp le nom des colonnes d'un fichier csv - - diff --git a/documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.qmd b/documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.qmd new file mode 100644 index 0000000..e6a2e50 --- /dev/null +++ b/documentations/openadom/fichiers/fichier_echange/data/components/pattern_components.qmd @@ -0,0 +1,125 @@ +--- + title: Colonnes avec pattern + subtitle: OA_patternComponents + abstract-title: > + Verticalisation qui parse selon une regexp le nom des colonnes d'un fichier csv. + abstract: > + <p>On peut utiliser OA_patternComponent pour rechercher des colonnes répondant à un pattern (OA_patternForComponents). + + <p>Les groupes capturés de l'expression régulière deviendront des sous composants (OA_componentQualifiers) du composant OA_patternComponent. + + <p>Il sera possible de capturer les valeurs des colonnes adjacentes répondant à un pattern définit (OA_importHeaderPattern) qui deviendront des des sous composants (OA_componentAdjacents). + + <p>Il y aura une verticalisation des colonnes (OA_patternComponents). Chaque colonne capturé sera enregistrée dans une nouvelle ligne. +--- + +Exemple de déclaration de section OA_patternComponents: + +::: {.callout-note collapse=false title="OA_data"} + +``` yaml +OA_data: + t_swc_swc: + OA_patternComponents: + swc_value: + OA_patternForComponents: "SWC(@?)_(.*)_(.*)" + OA_required: false + OA_exportHeader: + OA_title: + fr: "valeur" + en: "value" + OA_description: + fr: "valeur" + en: "value" + OA_componentQualifiers: + - swc_variable: + OA_exportHeader: + OA_title: + fr: "Humidité volumique du sol" + en: "Soil water concentration" + OA_description: + fr: "variable mesurée" + en: "mesured variable" + OA_tags: [__ORDER_1__] + OA_defaultValue: + OA_expression: "'humidite_volumique_du_sol'" #optional + OA_checker: + OA_name: OA_reference + OA_params: + OA_reference: + OA_name: tr_variables_var + - swc_repetition: + OA_exportHeader: + OA_title: + fr: "répétition" + en: "repetition" + OA_description: + fr: "répétition de la variable" + en: "variable repetition" + OA_tags: [__ORDER_2__] + OA_checker: + OA_name: OA_integer + - swc_profondeur: + OA_exportHeader: + OA_title: + fr: "profondeur" + en: "depth" + OA_description: + fr: "profondeur de la mesure" + en: "depth of measurement" + OA_tags: [__ORDER_3__] + OA_checker: + OA_name: OA_float + OA_componentAdjacents: + - swc_quality_class: + OA_importHeaderPattern: "qc" + OA_tags: [__ORDER_4__] + OA_exportHeader: + OA_title: + fr: Indice de qualité + en: Quality class + OA_description: + fr correcte + en: 0 for valid value; 2 for invalid value + OA_required: false + OA_mandatory: false + OA_checker: + OA_name: OA_integer + OA_params: + OA_max: 2 + OA_min: 0 + OA_multiplicity: ONE +``` +::: + +(@) Définition du pattern +Pour des colonnes SWC_2_20 où 2 est la répétition de la mesure et 20 sa profondeur. + +``` yaml + OA_patternForComponents: "SWC(@?)_(.*)_(.*)" +``` +On utilise une [expression regulière](https://docs.python.org/fr/3/howto/regex.html) pour rechercher dans l'en-tête du fichier des colonnes. + +Les parenthèses correspondent à des groupes de capture. Ici (@?) est toujours une chaîne vide ce qui nous permet d'utiliser une {{< var page-refs.groovy.link >}} pour définir une valeur de remplacement + + +``` yaml + OA_defaultValue: + OA_expression: "'humidite_volumique_du_sol'" +``` +On aurait aussi pu utiliser +``` yaml + OA_patternForComponents: "(humidite_volumique_du_sol)_(.*)_(.*)" +``` +Mais cela aurait changé nos en-tête de colonne SWC_2_20 -> humidite_volumique_du_sol_2_20 + + +::: {.callout-important} +<p>Le parseur va rechercher toutes les colonnes {{< var page-refs.basic-comp.oa >}}. On recherche dans les colonnes restantes celles qui "matchent" un OA_patternForComponents. + +<p>Le comportement fiOA_allowUnexpectedColumnsnal dépendra de la valeur de OA_allowUnexpectedColumns. +::: + +(@) définition de la colonne pattern. + +Comme tous les composants \ No newline at end of file diff --git a/documentations/openadom/fichiers/fichier_echange/etiquettes.md b/documentations/openadom/fichiers/fichier_echange/etiquettes.qmd similarity index 77% rename from documentations/openadom/fichiers/fichier_echange/etiquettes.md rename to documentations/openadom/fichiers/fichier_echange/etiquettes.qmd index d6aa6fd..53161a9 100644 --- a/documentations/openadom/fichiers/fichier_echange/etiquettes.md +++ b/documentations/openadom/fichiers/fichier_echange/etiquettes.qmd @@ -1,10 +1,11 @@ ### <a id="tags" />Etiquettes (OA_tags) -__OA_tags__: Création d'un regroupements sous une étiquette permettant de filtré l'affichages des listes des [__OA_data__](#data). -Mais aussi les [__OA_basicComponents__](#basicComponents), les [__OA_computedComponents__](#computedComponents), les [__OA_dynamicComponents__](#dynamicComponents) d'un [__OA_data__](#data). +__OA_tags__: Création d'un regroupements sous une étiquette permettant de filtrer l'affichage des listes des {{<var page-refs.etiquettes.link>}}. +Mais aussi les {{<var page-refs.basic-comp.link>}}, les {{<var page-refs.computed-comp.link>}}, les {{<var page-refs.dynamic-comp.link>}}, les {{<var page-refs.basic-comp.link>}}, les {{<var page-refs.pattern-comp.link>}} , les {{<var page-refs.constant-comp.link>}} d'un {{<var page-refs.data.oe>}}. +::: ```yaml OA_tags: profondeur: @@ -99,15 +100,11 @@ OA_data: OA_importHeader: pheopigments chl_unit: ``` - ->  Le tag n'est pas obligatoire. -> Si vous n'en mettez pas un, un tag par défaut se mettra. -> * Pour les components -> ```no-tag``` : sans étiquette. Ce qui permettra de filtré au même titre que ceux avec une étiquette créé par vous. -> * Pour les datas -> ```__REFERENCE__```. Ce qui permettra de filtré les datas par type. -> - ->  Le nom du tag est libre. -> Cependant, pour ceux réutilisés ailleurs dans l'application, il est préférable de n'utiliser que des minuscules et -> underscores sous peine de générer des erreurs dans les requête sql ou la création des vues. +:::{.callout-caution title="Le tag n'est pas obligatoire"} +Si vous n'en mettez pas un, un tag par défaut se mettra. + * Pour les components -> ```no-tag``` : sans étiquette. Ce qui permettra de filtré au même titre que ceux avec une étiquette créé par vous. + * Pour les datas -> ```__REFERENCE__```. Ce qui permettra de filtré les datas par type. +::: + diff --git a/documentations/openadom/fichiers/fichier_echange/submission.qmd b/documentations/openadom/fichiers/fichier_echange/submission.qmd new file mode 100644 index 0000000..4986b06 --- /dev/null +++ b/documentations/openadom/fichiers/fichier_echange/submission.qmd @@ -0,0 +1,7 @@ +--- +title: Stratégie de dépôt +subtitle: OA_submission +abstract: > + Cette section permet d'explicité comment la section OA_submission permet de définir une stratégie de dépôt des données. +--- +TODO \ No newline at end of file diff --git a/documentations/openadom/fichiers/fichier_echange/validations.qmd b/documentations/openadom/fichiers/fichier_echange/validations.qmd new file mode 100644 index 0000000..5a3db59 --- /dev/null +++ b/documentations/openadom/fichiers/fichier_echange/validations.qmd @@ -0,0 +1,8 @@ +--- +title: Validations +subtitle: OA_validations +abstract: > + Cette section vous permet de définir des règles qui s'appliquent à un ensemble de composants ou dont la règle fait intervenir plusieurs composants. +--- + +TODO \ No newline at end of file diff --git a/documentations/openadom/fichiers/fichier_echange/verificateurs.md b/documentations/openadom/fichiers/fichier_echange/verificateurs.qmd similarity index 84% rename from documentations/openadom/fichiers/fichier_echange/verificateurs.md rename to documentations/openadom/fichiers/fichier_echange/verificateurs.qmd index 422bb66..f68b47a 100644 --- a/documentations/openadom/fichiers/fichier_echange/verificateurs.md +++ b/documentations/openadom/fichiers/fichier_echange/verificateurs.qmd @@ -1,7 +1,12 @@ +--- + title: Vérificateurs + subtitle: OA_checker + abstract: > + Les vérificateurs (checkers) permettent de vérifier l'entrée d'un "component" et éventuellement de spécifier son type (entier, valeur flottante, booolean, date, clef étrangère) +--- +On peut poser des contraintes sur les différentes composantes des données -#### On peut poser des contraintes sur les données de référence - -##### [Utilisation de vérificateurs (checker)](#dataChecker) +# [Utilisation de vérificateurs (checker)](#dataChecker) Pour chaque colonne, on peut ajouter des vérificateurs. @@ -12,6 +17,8 @@ Pour chaque colonne, on peut ajouter des vérificateurs. - déclarer une hiérarchie entre composants - vérifier la valeur en utilisant un script (le script renvoyant true) ( GroovyExpression) +::: {.callout-note title="Utilisation des vérificateurs (OA_checker)" collapse="false"} + ```yaml sites: #donnée de référence avec une clef sur une colonne @@ -53,11 +60,12 @@ Pour chaque colonne, on peut ajouter des vérificateurs. OA_name: OA_integer # la valeur attendue est un entier OA_min: 100 # la valeur minimum acceptée ``` - +::: ### <a id="dataChecker" />Paramétrage des vérificateurs On définit un vérificateur dans une section "OA_checker". Le type de vérificateur est défini par son nom (OA_name). + On peut passer des paramètres au vérificateur en renseignant la section OA_params. Les différents paramètres dépendent du type de vérificateur utilisé. @@ -65,23 +73,42 @@ du type de vérificateur utilisé. OA_checker: OA_name: OA_integer OA_params: + OA_min: 0 +``` +Lorsque l'on utilise un vérificateur, sa première fonction est de vérifier le format de la valeur en entrée. +Sa seconde fonction est de transformer cette valeur , dans le cas où cela est possible, dans une primitive acceptable dans un champ json (numeric, boolean). C'est cette valeur qui sera stockée dan le champ json en base, ou comme valeur dans les vues. + +::: {.callout-note title="enregistrement de date" collapse="true"} +La date est stockée au format texte dans un format spécifique à l'application : "date:1984-01-05T00:00:00:dd/MM/yyyy". Elle peut alors être castée en utilisant le type "composite_date" + +``` postgresql + select ('date:1984-01-05T00:00:00:dd/MM/yyyy'::text::composite_date).*; + /* + datetimestamp formatteddate + 1984-01-05 00:00:00 dd/MM/yyyy + */ + select 'date:1984-01-05T00:00:00:dd/MM/yyyy'::text::composite_date::timestamp; -- 1984-01-05 00:00:00 + select ('date:1984-01-05T00:00:00:dd/MM/yyyy'::text::composite_date)::text; --05/01/1984 ``` -Lorsque l'on utilise un vérificateur, sa première fonction est de vérifier le format de la valeur en entrée : -Sa seconde fonction est de transformer cette valeur , dans le cas où cela est possible, dans une primitive acceptable dans un champ -json (numeric, boolean). C'est cette valeur qui sera stockée dan le champ json en base, ou comme valeur dans les vues. +::: + + +::: {.callout-note title="enregistrement de clef étrangère" collapse="true"} Si le vérificateur est de type Reference, il existera en base de données une contrainte de type clef étrangère avec la ligne référencée. +::: -###### Paramètres généraux +## Paramètres généraux -- OA_multiplicity : +::: {#multiplicity} +- OA_multiplicity : {#multiplicty} - MANY : La valeur est un ensemble (tableau) de valeurs. L'entrée est une chaîne ou chaque valeur est séparée par une virgule ','. - Dans la base de donnée les valeurs de la chaîne seront enregistrées dans un tableau de valeur au format indiqué par le vérificiateur. + Dans la base de donnée les valeurs de la chaîne seront enregistrées dans un tableau de valeur au format indiqué par le vérificateur. Par exemple la chaine "2,25.3,5.8" sera traitée comme un tableau de double [2,25.3,5.8] pour un vérificateur FLoat. - ONE : (valeur par défaut) La valeur en entrée est considéré comme une valeur simple. -- [transformations](#transformations) : La fonctionalité de transformation est supprimée. Pour le moment les référentiel sont à fournir au format clef primaire. +::: -###### <a id="numericChecker" />Vérificateur de type 'Integer' et 'Float' +## Vérificateur de type 'Integer' et 'Float'{#numericchecker} Ces vérificateurs servent à vérifier que les valeurs en entrée sont des nombres (respectivement des entiers ou des nombres à valeur floattante). @@ -95,7 +122,7 @@ On peut préciser les valeurs minimum et maximum en précisant les paramètres O OA_max: 25.0 OA_multiplicity: MANY ``` -###### <a id="stringChecker" />Vérificateur de chaîne ('String') +## <a id="stringChecker" />Vérificateur de chaîne ('String') Sans vérificateur, les entrées sont traitées comme des chaînes de caractères acceptant de valeurs vide. On peut toutefois rajouter un vérificateur chaîne pour préciser des contraintes sur la chaîne. (required, multiplicity, transformation, expression régulière) @@ -112,7 +139,7 @@ Le paramètre 'OA_pattern' permet de préciser une [expression régulière](http ``` Ce vérificateur permet de vérifier que l'entrée est une liste d'adresse mail. -###### <a id="dateChecker" />Vérificateur de date. ('Date') +## <a id="dateChecker" />Vérificateur de date. ('Date') Ce vérificateur permet de vérifier que la valeur en entrée est une date au format définit par le paramètre '[OA_pattern](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)' @@ -135,7 +162,7 @@ Une durée est définie au sens SQL d'un [interval](https://www.postgresql.org/d OA_max: 31/12/2025 OA_duration: 1 DAY ``` -###### <a id="booleanChecker" />Vérificateur de Boolean. ('Boolean') +## <a id="booleanChecker" />Vérificateur de Boolean. ('Boolean') Permet de vérifier que la valeur en entrée est true ou false. @@ -146,7 +173,7 @@ Une valeur booléenne sera enregistrée dans le champ json en base de données e OA_name: OA_boolean ``` -###### <a id="referenceChecker" />Vérificateur de référentiel. ('Reference') +## <a id="referenceChecker" />Vérificateur de référentiel. ('Reference') Ce vérificateur permet de vérifier que la valeur en entrée est un '[Ltree'https://www.postgresql.org/docs/current/ltree.html]'. Cette chaîne ne peut contenir que des termes contenant des minuscules/majuscules/chiffres/caractère_souligné(_), séparés par des points (.). @@ -173,7 +200,7 @@ OA_parent -> la colonne fait référence à un référentiel parent Il faut caster les valeurs du datum avant de les utiliser. Elles sont de type Object, et il faut les caster dans le type correspondant au checker. (par défaut String) -###### <a id="groovyChecker" />Vérificateur utilisant une [expression groovy](validation). ('GroovyExpression') +## <a id="groovyChecker" />Vérificateur utilisant une [expression groovy](validation). ('GroovyExpression') L'expression définit dans le paramètre groovy → expression; L'expression doit envoyer une faleur true/false. @@ -188,7 +215,7 @@ L'expression définit dans le paramètre groovy → expression; L'expression doi On vérifie que la composante 'qualité' de la variable 'SWC' est vide ou "0" "1" ou "2". -###### <a id="transformation" />Ajout de transformation à la chaîne en entrée. +## <a id="transformation" />Ajout de transformation à la chaîne en entrée. - OA_groovy : permet de déclarer une transformation de la valeur avec une expression Groovy (qui doit retourner une chaîne de caractère) @@ -245,7 +272,7 @@ Pour les checkers GroovyExpression et les transformations Groovy, on récupère -##### [Utilisation de validations portant sur une ou plusieurs colonnes](#dataChecker) +# [Utilisation de validations portant sur une ou plusieurs colonnes](#dataChecker) Les contraintes se définissent pour chacune des données de référence. Soit dans la définition de la colonne elle-même, soit dans la section [validation](#referencesValidation). diff --git a/documentations/openadom/fichiers/introduction/yaml.qmd b/documentations/openadom/fichiers/introduction/fichier_csv.qmd similarity index 50% rename from documentations/openadom/fichiers/introduction/yaml.qmd rename to documentations/openadom/fichiers/introduction/fichier_csv.qmd index 315bc63..b892700 100644 --- a/documentations/openadom/fichiers/introduction/yaml.qmd +++ b/documentations/openadom/fichiers/introduction/fichier_csv.qmd @@ -6,22 +6,29 @@ C'est un format tabulaire, avec des champs séparés par des points-virgules : *Example de fichier d'échange* - +::: {.callout-note title="Example de fichier d'échange" collapse="true"} + +::: Comme on peut le voir dans cet example, un fichier csv est composé de lignes composées de colonnes. -Un champ est ainsi repéré par un numéro de ligne et de colonne. -Un champ peut contenir 0, une ou plusieurs informations. +- Un champ est ainsi repéré par un numéro de ligne et de colonne. +- Un champ peut contenir 0, une ou plusieurs informations. -Dans l'application OpenAdom, nous +Dans l'application OpenAdom, nous avons la possibilité d'étendre le format csv standard en définissant un "cartouche" c'es à dire des information avant l'en-tête (pré-header) et après l'en-tête avant les données (post-header). On peut voir ainsi : + - un en-tête, généralement utilisé pour renseigner des métadonnées (cartouche) - - la zone d'étude, - - le commentaire, - - un libellé pour le contenu de chaque colonne, - - le min et le max accepté dans chaque colonne. - - ... -- les données à partir de la ligne 13. + - pre-header + - la zone d'étude, + - le commentaire, + - header + - un libellé pour le contenu de chaque colonne, + - post-header + - le min et le max accepté dans chaque colonne. + - ... + - data + - les données à partir de la ligne 13. La ligne 10 est la ligne d'en-tête de colonne. (_Date_, _SWC_1_10_) @@ -31,6 +38,6 @@ Les lignes 11 et 12 contiennent des informations spécifiques de chaque colonnes A partir de la ligne 13, on a les données proprement dîtes. _01/01/1999_ est une donnée de la colonne _Date_ -Enfin, un champs peut être vide, contenir une ou plusieurs informations. +Enfin, un champ peut être vide, contenir une ou plusieurs informations. -dans le fichier de configuration, vous devrez décrire votre format d'échange de données. \ No newline at end of file +Dans le fichier de configuration, vous devrez décrire votre format d'échange de données. \ No newline at end of file diff --git a/documentations/openadom/fichiers/introduction/vocabulaire.qmd b/documentations/openadom/fichiers/introduction/vocabulaire.qmd index 786e493..529c8ae 100644 --- a/documentations/openadom/fichiers/introduction/vocabulaire.qmd +++ b/documentations/openadom/fichiers/introduction/vocabulaire.qmd @@ -6,7 +6,7 @@ --- -# Clefs et code +# Clefs et code Dans un fichier, on définit une ou plusieurs colonnes qui correspondent à la clef d'idendification de la ligne. Cette clef naturelle permet lors d'une insertion / suppression de retrouver cette ligne dans la base de données et, si elle est présente, de la mettre à jour. Dans le cas contraire, une nouvelle ligne est créée. @@ -62,4 +62,37 @@ __component__ : un ensemble de valeur qui servent à décrire la donnée. CeS va __authorizationScope__ : une ou des informations contextuelles (variable-component) qui ont du sens pour limiter les autorisations. -__timeScope__ : l'information de temporalité d'une ligne ayant du sens pour limiter des authorisations à une période. \ No newline at end of file +__timeScope__ : l'information de temporalité d'une ligne ayant du sens pour limiter des authorisations à une période. + +# Identificateurs + +Lorsque l'on doit déclarer un ensemble de descriptions dans une section, on leur attribue un identificateur unique. + +Par exemple pour déclarer les descriptions des référentiels, des types de données, des colonnes… + +Comme ces identificateurs sont repris comme nom de table ou de champs dans la base de données, ils doivent respecter certaines +règles imposées par PostgreSQL. + +::: {.callout-tip title="Règle de nommage des identificateurs" collapse="false"} +Les identificateurs SQL doivent commencer avec une lettre minuscule, Les caractères suivants dans un identificateur peuvent être des lettres, des tirets bas ou des chiffres (0-9). + +De plus leur longueur ne peut dépasser 63 caractères. Il faut prendre en compte que lors de la création des vues, les identificateurs peuvent être combinés entre eux ou préfixés / suffixés. Il est donc préférable d'utiliser des noms courts. + +Vous serez informés lors du dépôt du fichier d'identificateurs incorrects. +::: + +::: {.callout-tip title="Convention de nommage des identificateurs" collapse="false"} +Il est conseillé d'utiliser une [convention de nommage](https://sqlpro.developpez.com/cours/standards/) pour choisir un identificateur. + +- pour un [référentiel](#references) le préfixe tr pour table référentiel, le nom du référentiel et un trigramme unique pour ce référentiel : tr_villes_vil +- pour une [donnée](#data) le préfixe t pour table fonctionnelle, le nom du type de données et un trigramme unique : t_meteo_met +- pour les [colonnes](#columns), on préfixe avec le trigramme de la table d'origine suivit du nom explicite de la colonne : + - vil_nom + - met_temperature + +L'utilisation de convention de nommage rendra la description de votre fichier de configuraion plus lisible, +ainsi que la compréhension des vues et tables générées automatiquement. +::: + +Ces identificateurs seront aussi les clefs pour les valeurs dans le champ JSON (refValues pour les référentiels; +dataValues pour les données ; les variables et les composantes) diff --git a/documentations/openadom/img/application-en.png b/documentations/openadom/img/application-en.png new file mode 100644 index 0000000000000000000000000000000000000000..1378b3e11a139989d125582c9bb51cd8bd2e458a GIT binary patch literal 30041 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 literal 0 HcmV?d00001 diff --git a/documentations/openadom/img/application_fr.png b/documentations/openadom/img/application_fr.png new file mode 100644 index 0000000000000000000000000000000000000000..0270c0645a71dafef3f363256ef6fce5c07ae4aa GIT binary patch literal 30402 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õhaq!ncLR~C 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 bydZwMaecqSKNj-OAgcT)C7Eg|laT)f4qsIQ literal 0 HcmV?d00001 -- GitLab From b41b61e9aa8756f997492b392f4a7747894275b6 Mon Sep 17 00:00:00 2001 From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr> Date: Thu, 16 Jan 2025 14:37:39 +0100 Subject: [PATCH 4/5] =?UTF-8?q?Modification=20du=20calcul=20de=20la=20date?= =?UTF-8?q?=20formatt=C3=A9e=20dans=20postgresql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pour une mise à jour d'un ancien schema: ``` postgresql DROP CAST IF EXISTS (COMPOSITE_DATE AS Text); DROP FUNCTION IF EXISTS castCompositeDateToFormattedDate(COMPOSITE_DATE); CREATE FUNCTION castCompositeDateToFormattedDate(COMPOSITE_DATE) RETURNS Text AS 'select to_char(($1)::timestamp, ($1).formattedDate::text);' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; CREATE CAST (COMPOSITE_DATE AS Text) WITH FUNCTION castCompositeDateToFormattedDate(COMPOSITE_DATE) AS ASSIGNMENT; ``` --- src/main/resources/migration/main/V1__init_schema.sql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/resources/migration/main/V1__init_schema.sql b/src/main/resources/migration/main/V1__init_schema.sql index e2abca5..c2cfce2 100644 --- a/src/main/resources/migration/main/V1__init_schema.sql +++ b/src/main/resources/migration/main/V1__init_schema.sql @@ -202,9 +202,14 @@ AS IMMUTABLE RETURNS NULL ON NULL INPUT; CREATE CAST (COMPOSITE_DATE AS TIMESTAMP) WITH FUNCTION castCompositeDateToTimestamp(COMPOSITE_DATE) AS ASSIGNMENT; + +DROP CAST IF EXISTS (COMPOSITE_DATE AS Text); +DROP FUNCTION IF EXISTS castCompositeDateToFormattedDate(COMPOSITE_DATE); + CREATE FUNCTION castCompositeDateToFormattedDate(COMPOSITE_DATE) RETURNS Text AS -'select ($1).formattedDate;' +'select to_char(($1)::timestamp, +($1).formattedDate::text);' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; -- GitLab From f42aba4539fc8c6206450f4829a4902ae626d166 Mon Sep 17 00:00:00 2001 From: philippe tcheriatinsky <philippe.tcherniatinsky@inrae.fr> Date: Thu, 16 Jan 2025 14:45:34 +0100 Subject: [PATCH 5/5] =?UTF-8?q?Modification=20de=20la=20d=C3=A9finition=20?= =?UTF-8?q?des=20sections=20de=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit validation et submision ne sont pas des alternatices mais des optionnels --- .../application/configuration/type/DataType.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/fr/inra/oresing/domain/application/configuration/type/DataType.java b/src/main/java/fr/inra/oresing/domain/application/configuration/type/DataType.java index 86a25c3..fbdc7a4 100644 --- a/src/main/java/fr/inra/oresing/domain/application/configuration/type/DataType.java +++ b/src/main/java/fr/inra/oresing/domain/application/configuration/type/DataType.java @@ -17,22 +17,20 @@ public record DataType(SectionBuilder sectionBuilder, Map<String, ConfigurationS new LabelDescription(ConfigurationSchemaNode.OA_ALLOW_UNEXPECTED_COLUMNS, new BooleanType(true)), new LabelDescription(ConfigurationSchemaNode.OA_SEPARATOR, StringType.EMPTY_INSTANCE()), new LabelDescription(ConfigurationSchemaNode.OA_TAGS, new CollectionType.ArrayType<>(List.of(), false, true, StringType.EMPTY_INSTANCE())), - new LabelDescription(ConfigurationSchemaNode.OA_I_18_N -, TitleType - .EMPTY_INSTANCE()), + new LabelDescription(ConfigurationSchemaNode.OA_I_18_N, TitleType.EMPTY_INSTANCE()), new LabelDescription(ConfigurationSchemaNode.OA_I_18_N_DISPLAY_PATTERN, TitleType.EMPTY_INSTANCE()), new LabelDescription(ConfigurationSchemaNode.OA_DATA_HEADER_LINE, IntegerType.EMPTY_INSTANCE()), new LabelDescription(ConfigurationSchemaNode.OA_DATA_FIRST_LINE, IntegerType.EMPTY_INSTANCE()), - new LabelDescription(ConfigurationSchemaNode.OA_AUTHORIZATION, AuthorizationType.EMPTY_INSTANCE()) + new LabelDescription(ConfigurationSchemaNode.OA_AUTHORIZATION, AuthorizationType.EMPTY_INSTANCE()), + new LabelDescription(ConfigurationSchemaNode.OA_VALIDATIONS, StaticMapType.VALIDATIONS().type), + new LabelDescription(ConfigurationSchemaNode.OA_SUBMISSION, SubmissionType.EMPTY_INSTANCE()) ) .withAnyOfMandatorySections( new LabelDescription(ConfigurationSchemaNode.OA_BASIC_COMPONENTS, BasicComponentType.EMPTY_INSTANCE()), new LabelDescription(ConfigurationSchemaNode.OA_COMPUTED_COMPONENTS, ComputedComponentType.EMPTY_INSTANCE()), new LabelDescription(ConfigurationSchemaNode.OA_DYNAMIC_COMPONENTS, DynamicComponentType.EMPTY_INSTANCE()), new LabelDescription(ConfigurationSchemaNode.OA_PATTERN_COMPONENTS, PatternComponentQualifierType.EMPTY_INSTANCE()), - new LabelDescription(ConfigurationSchemaNode.OA_CONSTANT_COMPONENTS, ConstantComponentType.EMPTY_INSTANCE()), - new LabelDescription(ConfigurationSchemaNode.OA_VALIDATIONS, StaticMapType.VALIDATIONS().type), - new LabelDescription(ConfigurationSchemaNode.OA_SUBMISSION, SubmissionType.EMPTY_INSTANCE()) + new LabelDescription(ConfigurationSchemaNode.OA_CONSTANT_COMPONENTS, ConstantComponentType.EMPTY_INSTANCE()) ); } public static DataType EMPTY_INSTANCE() { -- GitLab