Tony CHEMIT pushed to branch develop at ultreiaio / ird-observe

Commits:

20 changed files:

Changes:

  • client/datasource/editor/ps/src/main/i18n/getters/jaxx.getter
    ... ... @@ -190,6 +190,7 @@ observe.data.ps.observation.Catch.catchWeight
    190 190
     observe.data.ps.observation.Catch.maxWeight
    
    191 191
     observe.data.ps.observation.Catch.meanLength
    
    192 192
     observe.data.ps.observation.Catch.meanWeight
    
    193
    +observe.data.ps.observation.Catch.minMaxWeight
    
    193 194
     observe.data.ps.observation.Catch.minWeight
    
    194 195
     observe.data.ps.observation.Catch.reasonForDiscard
    
    195 196
     observe.data.ps.observation.Catch.totalCount
    

  • client/datasource/editor/ps/src/main/java/fr/ird/observe/client/datasource/editor/ps/data/observation/SetCatchUI.jaxx
    ... ... @@ -125,10 +125,13 @@
    125 125
             </row>
    
    126 126
             <row>
    
    127 127
                 <cell>
    
    128
    -                <JLabel id='minWeightLabel'/>
    
    128
    +                <JLabel id='minMaxWeightLabel'/>
    
    129 129
                 </cell>
    
    130 130
                 <cell weightx='1'>
    
    131
    -                <NumberEditor id='minWeight' styleClass="float2"/>
    
    131
    +                <JPanel layout="{new GridLayout()}">
    
    132
    +                    <NumberEditor id='minWeight' styleClass="float2"/>
    
    133
    +                    <NumberEditor id='maxWeight' styleClass="float2"/>
    
    134
    +                </JPanel>
    
    132 135
                 </cell>
    
    133 136
             </row>
    
    134 137
             <row>
    
    ... ... @@ -139,15 +142,6 @@
    139 142
                     <NumberEditor id='meanWeight' styleClass="float2"/>
    
    140 143
                 </cell>
    
    141 144
             </row>
    
    142
    -        <row>
    
    143
    -            <cell>
    
    144
    -                <JLabel id='maxWeightLabel'/>
    
    145
    -            </cell>
    
    146
    -            <cell weightx='1'>
    
    147
    -                <NumberEditor id='maxWeight' styleClass="float2"/>
    
    148
    -            </cell>
    
    149
    -        </row>
    
    150
    -
    
    151 145
             <!-- taille moyenne -->
    
    152 146
             <row>
    
    153 147
                 <cell>
    

  • core/api/services/src/main/i18n/getters/labels.getter
    ... ... @@ -1075,6 +1075,7 @@ observe.data.ps.observation.Catch.meanWeight
    1075 1075
     observe.data.ps.observation.Catch.meanWeight.short
    
    1076 1076
     observe.data.ps.observation.Catch.meanWeightComputed.computed.tip
    
    1077 1077
     observe.data.ps.observation.Catch.meanWeightComputed.observed.tip
    
    1078
    +observe.data.ps.observation.Catch.minMaxWeight
    
    1078 1079
     observe.data.ps.observation.Catch.minWeight
    
    1079 1080
     observe.data.ps.observation.Catch.minWeight.short
    
    1080 1081
     observe.data.ps.observation.Catch.reasonForDiscard
    

  • core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/common/TripSpi.java
    ... ... @@ -45,6 +45,7 @@ import fr.ird.observe.entities.referential.ps.common.AcquisitionStatus;
    45 45
     import fr.ird.observe.entities.referential.ps.common.ObservedSystem;
    
    46 46
     import fr.ird.observe.entities.referential.ps.common.Program;
    
    47 47
     import fr.ird.observe.entities.referential.ps.logbook.WellContentStatus;
    
    48
    +import fr.ird.observe.persistence.SqlHelper;
    
    48 49
     import fr.ird.observe.spi.service.ServiceContext;
    
    49 50
     import io.ultreia.java4all.util.Dates;
    
    50 51
     import io.ultreia.java4all.util.sql.SqlScriptWriter;
    
    ... ... @@ -330,8 +331,8 @@ public class TripSpi extends GeneratedTripSpi {
    330 331
                                  toId(observationsDataQuality),
    
    331 332
                                  toId(observer),
    
    332 333
                                  commentFormat.apply(observationsComment),
    
    333
    -                             escapeString(formsUrl),
    
    334
    -                             escapeString(reportsUrl),
    
    334
    +                             SqlHelper.escapeString(formsUrl),
    
    335
    +                             SqlHelper.escapeString(reportsUrl),
    
    335 336
                                  newId);
    
    336 337
         }
    
    337 338
     
    

  • core/persistence/resources/src/main/java/fr/ird/observe/persistence/avdth/data/DataWriter.java
    ... ... @@ -77,7 +77,7 @@ public abstract class DataWriter<E extends DataEntity, R extends DataReader<E>>
    77 77
         }
    
    78 78
     
    
    79 79
         public static String escapeString(String comment) {
    
    80
    -        return DataDtoEntityContext.escapeString(comment);
    
    80
    +        return SqlHelper.escapeString(comment);
    
    81 81
         }
    
    82 82
     
    
    83 83
         public static String roundFloat2(Float comment) {
    

  • core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/DataSourceMigrationForVersion_9_0.java
    ... ... @@ -23,7 +23,8 @@ package fr.ird.observe.spi.migration.v9;
    23 23
      */
    
    24 24
     
    
    25 25
     import com.google.auto.service.AutoService;
    
    26
    -import fr.ird.observe.spi.context.DataDtoEntityContext;
    
    26
    +import fr.ird.observe.dto.StringCleaner;
    
    27
    +import fr.ird.observe.persistence.SqlHelper;
    
    27 28
     import fr.ird.observe.spi.migration.ByMajorMigrationVersionResource;
    
    28 29
     import io.ultreia.java4all.util.Version;
    
    29 30
     import io.ultreia.java4all.util.sql.SqlQuery;
    
    ... ... @@ -254,6 +255,7 @@ public class DataSourceMigrationForVersion_9_0 extends ByMajorMigrationVersionRe
    254 255
                 executor.addScript("96", "add_referential_ps_common_ObservedSystem_finalize");
    
    255 256
             }
    
    256 257
         }
    
    258
    +
    
    257 259
         private void migrateCatches(MigrationVersionResourceExecutor executor) {
    
    258 260
     
    
    259 261
             Function<String, String> commentFormat = executor.commentFormat();
    
    ... ... @@ -395,7 +397,7 @@ public class DataSourceMigrationForVersion_9_0 extends ByMajorMigrationVersionRe
    395 397
                                                 sample.topiaId,
    
    396 398
                                                 sample.topiaVersion,
    
    397 399
                                                 sample.topiaCreateDate,
    
    398
    -                                            DataDtoEntityContext.escapeString(sample.homeId),
    
    400
    +                                            SqlHelper.escapeString(StringCleaner.ALL.apply(sample.homeId)),
    
    399 401
                                                 stringFormat.apply(sample.comment),
    
    400 402
                                                 sample.set,
    
    401 403
                                                 sample.lastUpdateDate
    
    ... ... @@ -564,31 +566,39 @@ public class DataSourceMigrationForVersion_9_0 extends ByMajorMigrationVersionRe
    564 566
                                                 sampleMeasure.topiaId,
    
    565 567
                                                 sampleMeasure.topiaVersion,
    
    566 568
                                                 sampleMeasure.topiaCreateDate,
    
    567
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.homeId == null ? null : sampleMeasure.homeId.replaceAll("'", "")),
    
    569
    +                                            SqlHelper.escapeString(sampleMeasure.homeId == null ? null : sampleMeasure.homeId.replaceAll("'", "")),
    
    568 570
                                                 sampleMeasure.length,
    
    569 571
                                                 sampleMeasure.isLengthComputed,
    
    570
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.picturesReferences == null ? null : sampleMeasure.picturesReferences.replaceAll("'", "")),
    
    572
    +                                            SqlHelper.escapeString(sampleMeasure.picturesReferences == null ? null : sampleMeasure.picturesReferences.replaceAll("'", "")),
    
    571 573
                                                 sampleMeasure.weight,
    
    572 574
                                                 sampleMeasure.isWeightComputed,
    
    573 575
                                                 sampleMeasure.count,
    
    574 576
                                                 sampleMeasure.acquisitionMode,
    
    575
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.species),
    
    577
    +                                            SqlHelper.escapeString(sampleMeasure.species),
    
    576 578
                                                 sampleId,
    
    577
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.sex),
    
    579
    +                                            SqlHelper.escapeString(sampleMeasure.sex),
    
    578 580
                                                 sampleMeasure.lastUpdateDate,
    
    579
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.sizeMeasureType),
    
    580
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.weightMeasureType),
    
    581
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.tagNumber),
    
    582
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.speciesFate),
    
    581
    +                                            SqlHelper.escapeString(sampleMeasure.sizeMeasureType),
    
    582
    +                                            SqlHelper.escapeString(sampleMeasure.weightMeasureType),
    
    583
    +                                            SqlHelper.escapeString(sampleMeasure.tagNumber),
    
    584
    +                                            SqlHelper.escapeString(sampleMeasure.speciesFate),
    
    583 585
                                                 sampleMeasure.sample_idx,
    
    584
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.lengthMeasureMethod),
    
    585
    -                                            DataDtoEntityContext.escapeString(sampleMeasure.weightMeasureMethod)
    
    586
    +                                            SqlHelper.escapeString(sampleMeasure.lengthMeasureMethod),
    
    587
    +                                            SqlHelper.escapeString(sampleMeasure.weightMeasureMethod)
    
    586 588
                 ));
    
    587 589
             }
    
    588 590
         }
    
    589 591
     
    
    590 592
         @Override
    
    591 593
         public void generateFinalizeSqlScript(MigrationVersionResourceExecutor executor) {
    
    594
    +        long stringFixedCount = new FixStringHelper(executor).execute();
    
    595
    +        if (stringFixedCount > 0) {
    
    596
    +            log.warn(String.format("Fix %s string rows(s).", stringFixedCount));
    
    597
    +        }
    
    598
    +        long commentFixedCount = new FixCommentHelper(executor).execute();
    
    599
    +        if (commentFixedCount > 0) {
    
    600
    +            log.warn(String.format("Fix %s comment rows(s).", commentFixedCount));
    
    601
    +        }
    
    592 602
             migrateIdx(executor, "ps_observation", "catch", "set");
    
    593 603
             migrateIdx(executor, "ps_observation", "SampleMeasure", "sample");
    
    594 604
         }
    

  • core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/DiscardedTargetCatchRecord.java
    ... ... @@ -22,6 +22,8 @@ package fr.ird.observe.spi.migration.v9;
    22 22
      * #L%
    
    23 23
      */
    
    24 24
     
    
    25
    +import fr.ird.observe.dto.StringCleaner;
    
    26
    +import fr.ird.observe.persistence.SqlHelper;
    
    25 27
     import fr.ird.observe.spi.context.DataDtoEntityContext;
    
    26 28
     
    
    27 29
     import java.sql.Connection;
    
    ... ... @@ -56,19 +58,19 @@ public class DiscardedTargetCatchRecord {
    56 58
     
    
    57 59
         public static PreparedStatement prepareStatement(Connection connection) throws SQLException {
    
    58 60
             return connection.prepareStatement("SELECT" +
    
    59
    -                                     /* 01 */      " REPLACE(tc.topiaId, '.TargetCatch', '.Catch')," +
    
    60
    -                                     /* 02 */      " tc.topiaVersion + 1," +
    
    61
    -                                     /* 03 */      " tc.topiaCreateDate," +
    
    62
    -                                     /* 04 */      " tc.homeId," +
    
    63
    -                                     /* 05 */      " tc.catchWeight," +
    
    64
    -                                     /* 06 */      " tc.weightCategory," +
    
    65
    -                                     /* 07 */      " tc.comment," +
    
    66
    -                                     /* 08 */      " tc.reasonForDiscard," +
    
    67
    -                                     /* 09 */      " tc.set," +
    
    68
    -                                     /* 10 */      " tc.lastUpdateDate," +
    
    69
    -                                     /* 11 */      " tc.well," +
    
    70
    -                                     /* 12 */      " -tc.set_idx," +
    
    71
    -                                     /* 13 */      " tc.weightMeasureMethod" +
    
    61
    +                                                   /* 01 */      " REPLACE(tc.topiaId, '.TargetCatch', '.Catch')," +
    
    62
    +                                                   /* 02 */      " tc.topiaVersion + 1," +
    
    63
    +                                                   /* 03 */      " tc.topiaCreateDate," +
    
    64
    +                                                   /* 04 */      " tc.homeId," +
    
    65
    +                                                   /* 05 */      " tc.catchWeight," +
    
    66
    +                                                   /* 06 */      " tc.weightCategory," +
    
    67
    +                                                   /* 07 */      " tc.comment," +
    
    68
    +                                                   /* 08 */      " tc.reasonForDiscard," +
    
    69
    +                                                   /* 09 */      " tc.set," +
    
    70
    +                                                   /* 10 */      " tc.lastUpdateDate," +
    
    71
    +                                                   /* 11 */      " tc.well," +
    
    72
    +                                                   /* 12 */      " -tc.set_idx," +
    
    73
    +                                                   /* 13 */      " tc.weightMeasureMethod" +
    
    72 74
                                                        " FROM ps_observation.TargetCatch tc" +
    
    73 75
                                                        " WHERE tc.discarded");
    
    74 76
         }
    
    ... ... @@ -132,24 +134,24 @@ public class DiscardedTargetCatchRecord {
    132 134
                                          "%17$s, " +
    
    133 135
                                          "%18$s" +
    
    134 136
                                          ");",
    
    135
    -                /*1*/                DataDtoEntityContext.escapeString(id),
    
    137
    +                /*1*/                SqlHelper.escapeString(id),
    
    136 138
                     /*2*/                topiaVersion,
    
    137 139
                     /*3*/                DataDtoEntityContext.timestamp(topiaCreateDate),
    
    138
    -                /*4*/                DataDtoEntityContext.escapeString(homeId),
    
    140
    +                /*4*/                SqlHelper.escapeString(StringCleaner.ALL.apply(homeId)),
    
    139 141
                     /*5*/                catchWeight,
    
    140 142
                     /*6*/                weightCategoryRecord.getMinWeight(),
    
    141 143
                     /*7*/                weightCategoryRecord.getMaxWeight(),
    
    142 144
                     /*8*/                null,
    
    143 145
                     /*9*/                getComment(weightCategoryRecord, commentFormat),
    
    144
    -                /*10*/               DataDtoEntityContext.escapeString(reasonForDiscardId),
    
    145
    -                /*11*/               DataDtoEntityContext.escapeString(weightCategoryRecord.getSpeciesId()),
    
    146
    -                /*12*/               DataDtoEntityContext.escapeString(DataSourceMigrationForVersion_9_0.SPECIES_FATE_5),
    
    147
    -                /*13*/               DataDtoEntityContext.escapeString(setId),
    
    146
    +                /*10*/               SqlHelper.escapeString(reasonForDiscardId),
    
    147
    +                /*11*/               SqlHelper.escapeString(weightCategoryRecord.getSpeciesId()),
    
    148
    +                /*12*/               SqlHelper.escapeString(DataSourceMigrationForVersion_9_0.SPECIES_FATE_5),
    
    149
    +                /*13*/               SqlHelper.escapeString(setId),
    
    148 150
                     /*14*/               DataDtoEntityContext.timestamp(lastUpdateDate),
    
    149
    -                /*15*/               DataDtoEntityContext.escapeString(getWell()),
    
    151
    +                /*15*/               SqlHelper.escapeString(StringCleaner.ALL.apply(well)),
    
    150 152
                     /*16*/               setIdx,
    
    151
    -                /*17*/               DataDtoEntityContext.escapeString(weightMeasureMethodId == null ? "fr.ird.referential.common.WeightMeasureMethod#666#03" : weightCategoryId),
    
    152
    -                /*18*/               DataDtoEntityContext.escapeString(DataSourceMigrationForVersion_9_0.INFORMATION_SOURCE_O)
    
    153
    +                /*17*/               SqlHelper.escapeString(weightMeasureMethodId == null ? "fr.ird.referential.common.WeightMeasureMethod#666#03" : weightCategoryId),
    
    154
    +                /*18*/               SqlHelper.escapeString(DataSourceMigrationForVersion_9_0.INFORMATION_SOURCE_O)
    
    153 155
             );
    
    154 156
         }
    
    155 157
     
    
    ... ... @@ -160,14 +162,4 @@ public class DiscardedTargetCatchRecord {
    160 162
             return stringFormat.apply(comment + "\n" + weightCategoryRecord.toComment());
    
    161 163
         }
    
    162 164
     
    
    163
    -    public String getWell() {
    
    164
    -        String result = well;
    
    165
    -        if (result!=null) {
    
    166
    -            result = well.trim();
    
    167
    -            if (well.startsWith("'")) {
    
    168
    -                result = result.substring(1);
    
    169
    -            }
    
    170
    -        }
    
    171
    -        return result;
    
    172
    -    }
    
    173 165
     }

  • core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/FixCommentHelper.java
    1
    +package fr.ird.observe.spi.migration.v9;
    
    2
    +
    
    3
    +/*-
    
    4
    + * #%L
    
    5
    + * ObServe Core :: Persistence :: Resources
    
    6
    + * %%
    
    7
    + * Copyright (C) 2008 - 2022 IRD, Ultreia.io
    
    8
    + * %%
    
    9
    + * This program is free software: you can redistribute it and/or modify
    
    10
    + * it under the terms of the GNU General Public License as
    
    11
    + * published by the Free Software Foundation, either version 3 of the
    
    12
    + * License, or (at your option) any later version.
    
    13
    + *
    
    14
    + * This program is distributed in the hope that it will be useful,
    
    15
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    16
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    
    17
    + * GNU General Public License for more details.
    
    18
    + *
    
    19
    + * You should have received a copy of the GNU General Public
    
    20
    + * License along with this program.  If not, see
    
    21
    + * <http://www.gnu.org/licenses/gpl-3.0.html>.
    
    22
    + * #L%
    
    23
    + */
    
    24
    +
    
    25
    +import org.apache.logging.log4j.LogManager;
    
    26
    +import org.apache.logging.log4j.Logger;
    
    27
    +import org.nuiton.topia.service.migration.resources.MigrationVersionResourceExecutor;
    
    28
    +
    
    29
    +import java.sql.PreparedStatement;
    
    30
    +import java.sql.ResultSet;
    
    31
    +import java.util.Objects;
    
    32
    +import java.util.concurrent.atomic.AtomicLong;
    
    33
    +import java.util.function.Function;
    
    34
    +
    
    35
    +/**
    
    36
    + * To auto-trim string comment fields.
    
    37
    + * <p>
    
    38
    + * <strong>Note:</strong> If fixed value is empty or blank then set {@code null} value.
    
    39
    + * <p>
    
    40
    + * Created on 11/11/2022.
    
    41
    + *
    
    42
    + * @author Tony Chemit - dev@tchemit.fr
    
    43
    + * @since 9.0.17
    
    44
    + */
    
    45
    +public class FixCommentHelper {
    
    46
    +
    
    47
    +    private static final Logger log = LogManager.getLogger(FixCommentHelper.class);
    
    48
    +
    
    49
    +    private final MigrationVersionResourceExecutor executor;
    
    50
    +    private final AtomicLong count = new AtomicLong();
    
    51
    +    private final Function<String, String> commentFormat;
    
    52
    +
    
    53
    +    public FixCommentHelper(MigrationVersionResourceExecutor executor) {
    
    54
    +        this.executor = Objects.requireNonNull(executor);
    
    55
    +        commentFormat = executor.commentFormat();
    
    56
    +    }
    
    57
    +
    
    58
    +    public long execute() {
    
    59
    +
    
    60
    +        fixField("common.Vessel", "comment");
    
    61
    +
    
    62
    +        fixField("ll_common.GearUseFeatures", "comment");
    
    63
    +        fixField("ll_common.Program", "comment");
    
    64
    +        fixField("ll_common.Trip", "generalComment");
    
    65
    +        fixField("ll_common.Trip", "logbookComment");
    
    66
    +        fixField("ll_common.Trip", "observationsComment");
    
    67
    +
    
    68
    +        fixField("ll_landing.Landing", "comment");
    
    69
    +
    
    70
    +        fixField("ll_logbook.Activity", "comment");
    
    71
    +        fixField("ll_logbook.Catch", "comment");
    
    72
    +        fixField("ll_logbook.Set", "comment");
    
    73
    +        fixField("ll_logbook.Sample", "comment");
    
    74
    +
    
    75
    +        fixField("ll_observation.Activity", "comment");
    
    76
    +        fixField("ll_observation.Branchline", "comment");
    
    77
    +        fixField("ll_observation.Catch", "comment");
    
    78
    +        fixField("ll_observation.Set", "comment");
    
    79
    +
    
    80
    +        fixField("ps_common.GearUseFeatures", "comment");
    
    81
    +        fixField("ps_common.Program", "comment");
    
    82
    +        fixField("ps_common.Trip", "generalComment");
    
    83
    +        fixField("ps_common.Trip", "logbookComment");
    
    84
    +        fixField("ps_common.Trip", "observationsComment");
    
    85
    +
    
    86
    +        fixField("ps_localmarket.Batch", "origin");
    
    87
    +        fixField("ps_localmarket.Sample", "comment");
    
    88
    +        fixField("ps_localmarket.SampleSpecies", "comment");
    
    89
    +        fixField("ps_localmarket.Survey", "comment");
    
    90
    +
    
    91
    +        fixField("ps_logbook.Activity", "comment");
    
    92
    +        fixField("ps_logbook.Catch", "comment");
    
    93
    +        fixField("ps_logbook.FloatingObject", "comment");
    
    94
    +        fixField("ps_logbook.Route", "comment");
    
    95
    +        fixField("ps_logbook.Sample", "comment");
    
    96
    +        fixField("ps_logbook.SampleSpecies", "comment");
    
    97
    +        fixField("ps_logbook.TransmittingBuoy", "comment");
    
    98
    +
    
    99
    +        fixField("ps_observation.Activity", "comment");
    
    100
    +        fixField("ps_observation.Catch", "comment");
    
    101
    +        fixField("ps_observation.FloatingObject", "comment");
    
    102
    +        fixField("ps_observation.NonTargetCatchRelease", "comment");
    
    103
    +        fixField("ps_observation.Route", "comment");
    
    104
    +        fixField("ps_observation.Set", "comment");
    
    105
    +        fixField("ps_observation.TransmittingBuoy", "comment");
    
    106
    +        return count.get();
    
    107
    +    }
    
    108
    +
    
    109
    +    public void fixField(String gav, String field) {
    
    110
    +
    
    111
    +        executor.doSqlWork(connection -> {
    
    112
    +            try (PreparedStatement statement = connection.prepareStatement(String.format("SELECT topiaId, %2$s FROM %1$s WHERE %2$s IS NOT NULL", gav, field))) {
    
    113
    +                try (ResultSet resultSet = statement.executeQuery()) {
    
    114
    +                    while (resultSet.next()) {
    
    115
    +                        String fieldValue = resultSet.getString(2);
    
    116
    +                        String fixFieldValue = fieldValue.trim();
    
    117
    +                        if (!fieldValue.equals(fixFieldValue)) {
    
    118
    +                            if (fixFieldValue.isEmpty()) {
    
    119
    +                                fixFieldValue = null;
    
    120
    +                            }
    
    121
    +                            String id = resultSet.getString(1);
    
    122
    +                            String finalFieldValue = commentFormat.apply(fixFieldValue);
    
    123
    +                            log.info(String.format("Fix comment field %s.%s[%s] from\n[%s]\nto\n[%s]", gav, field, id, fieldValue, fixFieldValue));
    
    124
    +                            executor.writeSql(String.format("UPDATE %s SET %s = %s WHERE topiaId = '%s';", gav, field, finalFieldValue, id));
    
    125
    +                            count.incrementAndGet();
    
    126
    +                        }
    
    127
    +                    }
    
    128
    +                }
    
    129
    +            }
    
    130
    +        });
    
    131
    +
    
    132
    +    }
    
    133
    +}

  • core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/FixStringHelper.java
    1
    +package fr.ird.observe.spi.migration.v9;
    
    2
    +
    
    3
    +/*-
    
    4
    + * #%L
    
    5
    + * ObServe Core :: Persistence :: Resources
    
    6
    + * %%
    
    7
    + * Copyright (C) 2008 - 2022 IRD, Ultreia.io
    
    8
    + * %%
    
    9
    + * This program is free software: you can redistribute it and/or modify
    
    10
    + * it under the terms of the GNU General Public License as
    
    11
    + * published by the Free Software Foundation, either version 3 of the
    
    12
    + * License, or (at your option) any later version.
    
    13
    + *
    
    14
    + * This program is distributed in the hope that it will be useful,
    
    15
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    16
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    
    17
    + * GNU General Public License for more details.
    
    18
    + *
    
    19
    + * You should have received a copy of the GNU General Public
    
    20
    + * License along with this program.  If not, see
    
    21
    + * <http://www.gnu.org/licenses/gpl-3.0.html>.
    
    22
    + * #L%
    
    23
    + */
    
    24
    +
    
    25
    +import fr.ird.observe.dto.StringCleaner;
    
    26
    +import fr.ird.observe.persistence.SqlHelper;
    
    27
    +import org.apache.logging.log4j.LogManager;
    
    28
    +import org.apache.logging.log4j.Logger;
    
    29
    +import org.nuiton.topia.service.migration.resources.MigrationVersionResourceExecutor;
    
    30
    +
    
    31
    +import java.sql.Connection;
    
    32
    +import java.sql.PreparedStatement;
    
    33
    +import java.sql.ResultSet;
    
    34
    +import java.sql.SQLException;
    
    35
    +import java.util.Collections;
    
    36
    +import java.util.Map;
    
    37
    +import java.util.Objects;
    
    38
    +import java.util.Set;
    
    39
    +import java.util.TreeMap;
    
    40
    +import java.util.TreeSet;
    
    41
    +import java.util.concurrent.atomic.AtomicLong;
    
    42
    +
    
    43
    +/**
    
    44
    + * To auto-trim string fields and remove any {@code '} characters inside it.
    
    45
    + * <p>
    
    46
    + * <strong>Note:</strong> If fixed value is empty or blank then set {@code null} value.
    
    47
    + * <p>
    
    48
    + * Created on 11/11/2022.
    
    49
    + *
    
    50
    + * @author Tony Chemit - dev@tchemit.fr
    
    51
    + * @since 9.0.17
    
    52
    + */
    
    53
    +public class FixStringHelper {
    
    54
    +
    
    55
    +    private static final Logger log = LogManager.getLogger(FixStringHelper.class);
    
    56
    +
    
    57
    +    private final MigrationVersionResourceExecutor executor;
    
    58
    +    private final AtomicLong count = new AtomicLong();
    
    59
    +
    
    60
    +    public FixStringHelper(MigrationVersionResourceExecutor executor) {
    
    61
    +        this.executor = Objects.requireNonNull(executor);
    
    62
    +    }
    
    63
    +
    
    64
    +    static class FixStringEntityModel {
    
    65
    +
    
    66
    +        private final String gav;
    
    67
    +        private final Map<String, StringCleaner> fieldsActions;
    
    68
    +        private final Set<String> fieldsDeleteIfNull;
    
    69
    +
    
    70
    +        static FixStringEntityModel on(String gav, StringCleaner cleaner, String firstField, String... fields) {
    
    71
    +            return new FixStringEntityModel(gav).add(cleaner, firstField, fields);
    
    72
    +        }
    
    73
    +
    
    74
    +        static FixStringEntityModel onI18n(String gav, StringCleaner cleaner, String firstField, String... fields) {
    
    75
    +            return on(gav, StringCleaner.TRIM, "label1", "label2", "label3").add(cleaner, firstField, fields);
    
    76
    +        }
    
    77
    +
    
    78
    +        private FixStringEntityModel(String gav) {
    
    79
    +            this.gav = gav;
    
    80
    +            this.fieldsActions = new TreeMap<>();
    
    81
    +            this.fieldsDeleteIfNull = new TreeSet<>();
    
    82
    +        }
    
    83
    +
    
    84
    +        FixStringEntityModel add(StringCleaner cleaner, String firstField, String... fields) {
    
    85
    +            fieldsActions.put(firstField, cleaner);
    
    86
    +            for (String field : fields) {
    
    87
    +                fieldsActions.put(field, cleaner);
    
    88
    +            }
    
    89
    +            return this;
    
    90
    +        }
    
    91
    +
    
    92
    +        FixStringEntityModel deleteIfNull(String firstField, String... fields) {
    
    93
    +            fieldsDeleteIfNull.add(firstField);
    
    94
    +            Collections.addAll(fieldsDeleteIfNull, fields);
    
    95
    +            return this;
    
    96
    +        }
    
    97
    +
    
    98
    +    }
    
    99
    +
    
    100
    +    public long execute() {
    
    101
    +        executor.doSqlWork(connection -> {
    
    102
    +            execute(connection, FixStringEntityModel.onI18n("common.Country", StringCleaner.ALL, "code", "iso2Code", "iso3Code"));
    
    103
    +            execute(connection, FixStringEntityModel.onI18n("common.DataQuality", StringCleaner.ALL, "code"));
    
    104
    +            execute(connection, FixStringEntityModel.onI18n("common.FpaZone", StringCleaner.ALL, "code"));
    
    105
    +            execute(connection, FixStringEntityModel.onI18n("common.Gear", StringCleaner.ALL, "code"));
    
    106
    +            execute(connection, FixStringEntityModel.onI18n("common.GearCharacteristic", StringCleaner.ALL, "code"));
    
    107
    +            execute(connection, FixStringEntityModel.onI18n("common.GearCharacteristicType", StringCleaner.ALL, "code"));
    
    108
    +            execute(connection, FixStringEntityModel.onI18n("common.Harbour", StringCleaner.ALL, "code"));
    
    109
    +            execute(connection, FixStringEntityModel.on("common.LengthLengthParameter", StringCleaner.ALL, "coefficients", "inputOutputFormula", "outputInputFormula"));
    
    110
    +            execute(connection, FixStringEntityModel.onI18n("common.LengthMeasureMethod", StringCleaner.ALL, "code"));
    
    111
    +            execute(connection, FixStringEntityModel.on("common.LengthWeightParameter", StringCleaner.ALL, "coefficients", "lengthWeightFormula", "weightLengthFormula"));
    
    112
    +            execute(connection, FixStringEntityModel.onI18n("common.Ocean", StringCleaner.ALL, "code"));
    
    113
    +            execute(connection, FixStringEntityModel.onI18n("common.Organism", StringCleaner.ALL, "code"));
    
    114
    +            // not removing single quotes
    
    115
    +            execute(connection, FixStringEntityModel.on("common.Person", StringCleaner.TRIM, "firstName", "lastName"));
    
    116
    +            execute(connection, FixStringEntityModel.onI18n("common.Sex", StringCleaner.ALL, "code"));
    
    117
    +            execute(connection, FixStringEntityModel.on("common.ShipOwner", StringCleaner.ALL, "code", "label"));
    
    118
    +            execute(connection, FixStringEntityModel.onI18n("common.SizeMeasureType", StringCleaner.ALL, "code"));
    
    119
    +            execute(connection, FixStringEntityModel.onI18n("common.Species", StringCleaner.ALL, "scientificLabel"));
    
    120
    +            execute(connection, FixStringEntityModel.onI18n("common.SpeciesGroup", StringCleaner.ALL, "code"));
    
    121
    +            execute(connection, FixStringEntityModel.onI18n("common.SpeciesGroupReleaseMode", StringCleaner.ALL, "code"));
    
    122
    +            execute(connection, FixStringEntityModel.onI18n("common.SpeciesList", StringCleaner.ALL, "code"));
    
    123
    +            execute(connection, FixStringEntityModel.onI18n("common.Vessel", StringCleaner.ALL, "code"));
    
    124
    +            execute(connection, FixStringEntityModel.onI18n("common.VesselType", StringCleaner.ALL, "code"));
    
    125
    +            execute(connection, FixStringEntityModel.on("common.VesselSizeCategory", StringCleaner.ALL, "code", "capacityLabel", "gaugeLabel"));
    
    126
    +            execute(connection, FixStringEntityModel.onI18n("common.WeightMeasureMethod", StringCleaner.ALL, "code"));
    
    127
    +            execute(connection, FixStringEntityModel.onI18n("common.WeightMeasureType", StringCleaner.ALL, "code"));
    
    128
    +            execute(connection, FixStringEntityModel.onI18n("common.Wind", StringCleaner.ALL, "code"));
    
    129
    +
    
    130
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.BaitSettingStatus", StringCleaner.ALL, "code"));
    
    131
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.BaitType", StringCleaner.ALL, "code"));
    
    132
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.CatchFate", StringCleaner.ALL, "code"));
    
    133
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.HealthStatus", StringCleaner.ALL, "code"));
    
    134
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.HookSize", StringCleaner.ALL, "code"));
    
    135
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.HookType", StringCleaner.ALL, "code"));
    
    136
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.LightsticksColor", StringCleaner.ALL, "code"));
    
    137
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.LightsticksType", StringCleaner.ALL, "code"));
    
    138
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.LineType", StringCleaner.ALL, "code"));
    
    139
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.MitigationType", StringCleaner.ALL, "code"));
    
    140
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.ObservationMethod", StringCleaner.ALL, "code"));
    
    141
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.OnBoardProcessing", StringCleaner.ALL, "code"));
    
    142
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.Program", StringCleaner.ALL, "code"));
    
    143
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.SettingShape", StringCleaner.ALL, "code"));
    
    144
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.TripType", StringCleaner.ALL, "code"));
    
    145
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.VesselActivity", StringCleaner.ALL, "code"));
    
    146
    +            execute(connection, FixStringEntityModel.onI18n("ll_common.WeightDeterminationMethod", StringCleaner.ALL, "code"));
    
    147
    +
    
    148
    +            execute(connection, FixStringEntityModel.onI18n("ll_landing.Company", StringCleaner.ALL, "code"));
    
    149
    +            execute(connection, FixStringEntityModel.onI18n("ll_landing.Conservation", StringCleaner.ALL, "code"));
    
    150
    +            execute(connection, FixStringEntityModel.onI18n("ll_landing.DataSource", StringCleaner.ALL, "code"));
    
    151
    +
    
    152
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.BaitHaulingStatus", StringCleaner.ALL, "code"));
    
    153
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.EncounterType", StringCleaner.ALL, "code"));
    
    154
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.HookPosition", StringCleaner.ALL, "code"));
    
    155
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.ItemHorizontalPosition", StringCleaner.ALL, "code"));
    
    156
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.ItemVerticalPosition", StringCleaner.ALL, "code"));
    
    157
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.MaturityStatus", StringCleaner.ALL, "code"));
    
    158
    +            execute(connection, FixStringEntityModel.on("ll_observation.SensorBrand", StringCleaner.ALL, "brandName", "code"));
    
    159
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.SensorDataFormat", StringCleaner.ALL, "code"));
    
    160
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.SensorType", StringCleaner.ALL, "code"));
    
    161
    +            execute(connection, FixStringEntityModel.onI18n("ll_observation.StomachFullness", StringCleaner.ALL, "code"));
    
    162
    +
    
    163
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.AcquisitionStatus", StringCleaner.ALL, "code"));
    
    164
    +            // not set to null if empty (special value FOB has an empty code)
    
    165
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.ObjectMaterial", StringCleaner.REMOVE_SINGLE_QUOTE_AND_TRIM, "code"));
    
    166
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.ObjectMaterialType", StringCleaner.ALL, "code"));
    
    167
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.ObjectOperation", StringCleaner.ALL, "code"));
    
    168
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.ObservedSystem", StringCleaner.ALL, "code"));
    
    169
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.Program", StringCleaner.ALL, "code"));
    
    170
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.ReasonForNoFishing", StringCleaner.ALL, "code"));
    
    171
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.ReasonForNullSet", StringCleaner.ALL, "code"));
    
    172
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.SampleType", StringCleaner.ALL, "code"));
    
    173
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.SchoolType", StringCleaner.ALL, "code"));
    
    174
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.SpeciesFate", StringCleaner.ALL, "code"));
    
    175
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.TransmittingBuoyOperation", StringCleaner.ALL, "code"));
    
    176
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.TransmittingBuoyOwnership", StringCleaner.ALL, "code"));
    
    177
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.TransmittingBuoyType", StringCleaner.ALL, "code"));
    
    178
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.VesselActivity", StringCleaner.ALL, "code"));
    
    179
    +            execute(connection, FixStringEntityModel.onI18n("ps_common.WeightCategory", StringCleaner.ALL, "code"));
    
    180
    +
    
    181
    +            execute(connection, FixStringEntityModel.onI18n("ps_landing.Destination", StringCleaner.ALL, "code"));
    
    182
    +            execute(connection, FixStringEntityModel.onI18n("ps_landing.Fate", StringCleaner.ALL, "code"));
    
    183
    +
    
    184
    +            execute(connection, FixStringEntityModel.onI18n("ps_localmarket.BatchComposition", StringCleaner.ALL, "code"));
    
    185
    +            execute(connection, FixStringEntityModel.onI18n("ps_localmarket.BatchWeightType", StringCleaner.ALL, "code"));
    
    186
    +            execute(connection, FixStringEntityModel.onI18n("ps_localmarket.Packaging", StringCleaner.ALL, "code"));
    
    187
    +
    
    188
    +            execute(connection, FixStringEntityModel.onI18n("ps_logbook.InformationSource", StringCleaner.ALL, "code"));
    
    189
    +            execute(connection, FixStringEntityModel.onI18n("ps_logbook.SampleQuality", StringCleaner.ALL, "code"));
    
    190
    +            execute(connection, FixStringEntityModel.onI18n("ps_logbook.SetSuccessStatus", StringCleaner.ALL, "code"));
    
    191
    +            execute(connection, FixStringEntityModel.onI18n("ps_logbook.WellContentStatus", StringCleaner.ALL, "code"));
    
    192
    +            execute(connection, FixStringEntityModel.onI18n("ps_logbook.WellSamplingConformity", StringCleaner.ALL, "code"));
    
    193
    +            execute(connection, FixStringEntityModel.onI18n("ps_logbook.WellSamplingStatus", StringCleaner.ALL, "code"));
    
    194
    +
    
    195
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.DetectionMode", StringCleaner.ALL, "code"));
    
    196
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.InformationSource", StringCleaner.ALL, "code"));
    
    197
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.NonTargetCatchReleaseConformity", StringCleaner.ALL, "code"));
    
    198
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.NonTargetCatchReleaseStatus", StringCleaner.ALL, "code"));
    
    199
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.NonTargetCatchReleasingTime", StringCleaner.ALL, "code"));
    
    200
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.ReasonForDiscard", StringCleaner.ALL, "code"));
    
    201
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.SpeciesStatus", StringCleaner.ALL, "code"));
    
    202
    +            execute(connection, FixStringEntityModel.onI18n("ps_observation.SurroundingActivity", StringCleaner.ALL, "code"));
    
    203
    +
    
    204
    +            execute(connection, FixStringEntityModel.on("ll_common.GearUseFeaturesMeasurement", StringCleaner.ALL, "measurementValue").deleteIfNull("measurementValue"));
    
    205
    +            execute(connection, FixStringEntityModel.on("ll_common.Trip", StringCleaner.ALL, "ersId", "homeId"));
    
    206
    +
    
    207
    +            execute(connection, FixStringEntityModel.on("ll_logbook.Catch", StringCleaner.ALL, "photoReferences", "tagNumber"));
    
    208
    +            execute(connection, FixStringEntityModel.on("ll_logbook.SamplePart", StringCleaner.ALL, "tagNumber"));
    
    209
    +            execute(connection, FixStringEntityModel.on("ll_logbook.Set", StringCleaner.ALL, "homeId"));
    
    210
    +
    
    211
    +            execute(connection, FixStringEntityModel.on("ll_observation.Catch", StringCleaner.ALL, "photoReferences", "tagNumber"));
    
    212
    +            execute(connection, FixStringEntityModel.on("ll_observation.SensorUsed", StringCleaner.ALL, "sensorSerialNo"));
    
    213
    +            execute(connection, FixStringEntityModel.on("ll_observation.Set", StringCleaner.ALL, "homeId"));
    
    214
    +            execute(connection, FixStringEntityModel.on("ll_observation.Tdr", StringCleaner.ALL, "serialNo"));
    
    215
    +
    
    216
    +            execute(connection, FixStringEntityModel.on("ps_common.GearUseFeaturesMeasurement", StringCleaner.ALL, "measurementValue").deleteIfNull("measurementValue"));
    
    217
    +            execute(connection, FixStringEntityModel.on("ps_common.Trip", StringCleaner.ALL, "ersId", "formsUrl", "homeId", "reportsUrl"));
    
    218
    +
    
    219
    +            execute(connection, FixStringEntityModel.on("ps_localmarket.Sample", StringCleaner.ALL, "number"));
    
    220
    +
    
    221
    +            execute(connection, FixStringEntityModel.on("ps_logbook.Catch", StringCleaner.ALL, "well"));
    
    222
    +            execute(connection, FixStringEntityModel.on("ps_logbook.FloatingObject", StringCleaner.ALL, "supportVesselName"));
    
    223
    +            execute(connection, FixStringEntityModel.on("ps_logbook.Sample", StringCleaner.ALL, "well"));
    
    224
    +            execute(connection, FixStringEntityModel.on("ps_logbook.TransmittingBuoy", StringCleaner.ALL, "code"));
    
    225
    +            execute(connection, FixStringEntityModel.on("ps_logbook.WellPlan", StringCleaner.ALL, "well"));
    
    226
    +
    
    227
    +            execute(connection, FixStringEntityModel.on("ps_observation.Activity", StringCleaner.ALL, "ersId"));
    
    228
    +            execute(connection, FixStringEntityModel.on("ps_observation.FloatingObject", StringCleaner.ALL, "supportVesselName"));
    
    229
    +            execute(connection, FixStringEntityModel.on("ps_observation.SampleMeasure", StringCleaner.ALL, "picturesReferences", "tagNumber"));
    
    230
    +            execute(connection, FixStringEntityModel.on("ps_observation.Set", StringCleaner.ALL, "supportVesselName"));
    
    231
    +            execute(connection, FixStringEntityModel.on("ps_observation.TransmittingBuoy", StringCleaner.ALL, "code"));
    
    232
    +        });
    
    233
    +        return count.get();
    
    234
    +    }
    
    235
    +
    
    236
    +    void execute(Connection connection, FixStringEntityModel model) throws SQLException {
    
    237
    +        for (Map.Entry<String, StringCleaner> entry : model.fieldsActions.entrySet()) {
    
    238
    +            execute(connection, model.gav, entry.getKey(), entry.getValue(), model.fieldsDeleteIfNull.contains(entry.getKey()));
    
    239
    +        }
    
    240
    +    }
    
    241
    +
    
    242
    +    void execute(Connection connection, String gav, String field, StringCleaner cleaner, boolean deleteIfNull) throws SQLException {
    
    243
    +        try (PreparedStatement statement = connection.prepareStatement(String.format("SELECT topiaId, %2$s FROM %1$s WHERE %2$s IS NOT NULL", gav, field))) {
    
    244
    +            try (ResultSet resultSet = statement.executeQuery()) {
    
    245
    +                while (resultSet.next()) {
    
    246
    +                    String fieldValue = resultSet.getString(2);
    
    247
    +                    String fixFieldValue = cleaner.apply(fieldValue);
    
    248
    +                    if (!fieldValue.equals(fixFieldValue)) {
    
    249
    +                        String id = resultSet.getString(1);
    
    250
    +                        if (deleteIfNull && fixFieldValue == null) {
    
    251
    +                            log.warn(String.format("Delete row since field is empty %s.%s[%s] (was '%s')", gav, field, id, fieldValue));
    
    252
    +                            executor.writeSql(String.format("DELETE FROM %1$s WHERE topiaId = '%2$s';", gav, id));
    
    253
    +                        } else {
    
    254
    +                            log.info(String.format("Fix string field %s.%s[%s] from\n[%s]\n to\n[%s]", gav, field, id, fieldValue, fixFieldValue));
    
    255
    +                            String finalFieldValue = SqlHelper.escapeString(fixFieldValue);
    
    256
    +                            executor.writeSql(String.format("UPDATE %1$s SET %2$s = %3$s WHERE topiaId = '%4$s';", gav, field, finalFieldValue, id));
    
    257
    +                        }
    
    258
    +                        count.incrementAndGet();
    
    259
    +                    }
    
    260
    +                }
    
    261
    +            }
    
    262
    +        }
    
    263
    +    }
    
    264
    +}

  • core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/NotDiscardedTargetCatchRecord.java
    ... ... @@ -22,6 +22,8 @@ package fr.ird.observe.spi.migration.v9;
    22 22
      * #L%
    
    23 23
      */
    
    24 24
     
    
    25
    +import fr.ird.observe.dto.StringCleaner;
    
    26
    +import fr.ird.observe.persistence.SqlHelper;
    
    25 27
     import fr.ird.observe.spi.context.DataDtoEntityContext;
    
    26 28
     
    
    27 29
     import java.sql.Connection;
    
    ... ... @@ -42,19 +44,19 @@ class NotDiscardedTargetCatchRecord {
    42 44
     
    
    43 45
         public static PreparedStatement prepareStatement(Connection connection) throws SQLException {
    
    44 46
             return connection.prepareStatement("SELECT" +
    
    45
    -                                       /* 01 */    " REPLACE(tc.topiaId, '.TargetCatch', '.Catch')," +
    
    46
    -                                       /* 02 */    " tc.topiaVersion + 1," +
    
    47
    -                                       /* 03 */    " tc.topiaCreateDate," +
    
    48
    -                                       /* 04 */    " tc.homeId," +
    
    49
    -                                       /* 05 */    " tc.catchWeight," +
    
    50
    -                                       /* 06 */    " tc.weightCategory," +
    
    51
    -                                       /* 07 */    " tc.comment," +
    
    52
    -                                       /* 08 */    " tc.set," +
    
    53
    -                                       /* 09 */    " tc.lastUpdateDate," +
    
    54
    -                                       /* 10 */    " tc.well," +
    
    55
    -                                       /* 11 */    " -tc.set_idx," +
    
    56
    -                                       /* 12 */    " tc.weightMeasureMethod," +
    
    57
    -                                       /* 13 */    " s.targetcatchcompositionestimatedbyobserver " +
    
    47
    +                                                   /* 01 */    " REPLACE(tc.topiaId, '.TargetCatch', '.Catch')," +
    
    48
    +                                                   /* 02 */    " tc.topiaVersion + 1," +
    
    49
    +                                                   /* 03 */    " tc.topiaCreateDate," +
    
    50
    +                                                   /* 04 */    " tc.homeId," +
    
    51
    +                                                   /* 05 */    " tc.catchWeight," +
    
    52
    +                                                   /* 06 */    " tc.weightCategory," +
    
    53
    +                                                   /* 07 */    " tc.comment," +
    
    54
    +                                                   /* 08 */    " tc.set," +
    
    55
    +                                                   /* 09 */    " tc.lastUpdateDate," +
    
    56
    +                                                   /* 10 */    " tc.well," +
    
    57
    +                                                   /* 11 */    " -tc.set_idx," +
    
    58
    +                                                   /* 12 */    " tc.weightMeasureMethod," +
    
    59
    +                                                   /* 13 */    " s.targetcatchcompositionestimatedbyobserver " +
    
    58 60
                                                        " FROM ps_observation.TargetCatch tc INNER JOIN ps_observation.set s on s.topiaId = tc.set" +
    
    59 61
                                                        " WHERE NOT tc.discarded AND NOT ( weightCategory IS NULL AND catchweight IS NULL AND well IS NULL AND broughtondeck IS NULL AND reasonfordiscard IS NULL )");
    
    60 62
         }
    
    ... ... @@ -131,24 +133,24 @@ class NotDiscardedTargetCatchRecord {
    131 133
                                          "%16$s, " +
    
    132 134
                                          "%17$s, " +
    
    133 135
                                          "%18$s);",
    
    134
    -                /*1*/          DataDtoEntityContext.escapeString(id),
    
    136
    +                /*1*/          SqlHelper.escapeString(id),
    
    135 137
                     /*2*/          topiaVersion,
    
    136 138
                     /*3*/          DataDtoEntityContext.timestamp(topiaCreateDate),
    
    137
    -                /*4*/          DataDtoEntityContext.escapeString(homeId),
    
    139
    +                /*4*/          SqlHelper.escapeString(StringCleaner.ALL.apply(homeId)),
    
    138 140
                     /*5*/          catchWeight,
    
    139 141
                     /*6*/          weightCategoryRecord.getMinWeight(),
    
    140 142
                     /*7*/          weightCategoryRecord.getMaxWeight(),
    
    141 143
                     /*8*/          null,
    
    142 144
                     /*9*/          getComment(weightCategoryRecord, commentFormat),
    
    143 145
                     /*10*/         null,
    
    144
    -                /*11*/         DataDtoEntityContext.escapeString(weightCategoryRecord.getSpeciesId()),
    
    145
    -                /*12*/         DataDtoEntityContext.escapeString("10".equals(weightCategoryRecord.getCode()) ? DataSourceMigrationForVersion_9_0.SPECIES_FATE_15 : DataSourceMigrationForVersion_9_0.SPECIES_FATE_6),
    
    146
    -                /*13*/         DataDtoEntityContext.escapeString(setId),
    
    146
    +                /*11*/         SqlHelper.escapeString(weightCategoryRecord.getSpeciesId()),
    
    147
    +                /*12*/         SqlHelper.escapeString("10".equals(weightCategoryRecord.getCode()) ? DataSourceMigrationForVersion_9_0.SPECIES_FATE_15 : DataSourceMigrationForVersion_9_0.SPECIES_FATE_6),
    
    148
    +                /*13*/         SqlHelper.escapeString(setId),
    
    147 149
                     /*14*/         DataDtoEntityContext.timestamp(lastUpdateDate),
    
    148
    -                /*15*/         DataDtoEntityContext.escapeString(getWell()),
    
    150
    +                /*15*/         SqlHelper.escapeString(StringCleaner.ALL.apply(well)),
    
    149 151
                     /*16*/         setIdx,
    
    150
    -                /*17*/         DataDtoEntityContext.escapeString(weightMeasureMethodId == null ? "fr.ird.referential.common.WeightMeasureMethod#666#03" : weightCategoryId),
    
    151
    -                /*18*/         DataDtoEntityContext.escapeString(targetCatchCompositionEstimatedByObserver ? DataSourceMigrationForVersion_9_0.INFORMATION_SOURCE_P : DataSourceMigrationForVersion_9_0.INFORMATION_SOURCE_U)
    
    152
    +                /*17*/         SqlHelper.escapeString(weightMeasureMethodId == null ? "fr.ird.referential.common.WeightMeasureMethod#666#03" : weightCategoryId),
    
    153
    +                /*18*/         SqlHelper.escapeString(targetCatchCompositionEstimatedByObserver ? DataSourceMigrationForVersion_9_0.INFORMATION_SOURCE_P : DataSourceMigrationForVersion_9_0.INFORMATION_SOURCE_U)
    
    152 154
             );
    
    153 155
         }
    
    154 156
     
    
    ... ... @@ -158,16 +160,4 @@ class NotDiscardedTargetCatchRecord {
    158 160
             }
    
    159 161
             return stringFormat.apply(comment + "\n" + weightCategoryRecord.toComment());
    
    160 162
         }
    
    161
    -
    
    162
    -
    
    163
    -    public String getWell() {
    
    164
    -        String result = well;
    
    165
    -        if (result!=null) {
    
    166
    -            result = well.trim();
    
    167
    -            if (well.startsWith("'")) {
    
    168
    -                result = result.substring(1);
    
    169
    -            }
    
    170
    -        }
    
    171
    -        return result;
    
    172
    -    }
    
    173 163
     }

  • core/services/i18n/src/main/i18n/translations/services_en_GB.properties
    ... ... @@ -1287,6 +1287,7 @@ observe.data.ps.observation.Catch.meanWeight.short=Mean weight
    1287 1287
     observe.data.ps.observation.Catch.meanWeight.validation.notFilled=Weight or mean size must be filled.
    
    1288 1288
     observe.data.ps.observation.Catch.meanWeightComputed.computed.tip=Mean weight was computed (%s)
    
    1289 1289
     observe.data.ps.observation.Catch.meanWeightComputed.observed.tip=Mean weight was observed
    
    1290
    +observe.data.ps.observation.Catch.minMaxWeight=Lower / upper weight limit (in kg)
    
    1290 1291
     observe.data.ps.observation.Catch.minWeight=Lower weight limit (in kg)
    
    1291 1292
     observe.data.ps.observation.Catch.minWeight.short=Min weight (in kg)
    
    1292 1293
     observe.data.ps.observation.Catch.reasonForDiscard=Reason for discard
    

  • core/services/i18n/src/main/i18n/translations/services_es_ES.properties
    ... ... @@ -1287,6 +1287,7 @@ observe.data.ps.observation.Catch.meanWeight.short=Peso medio
    1287 1287
     observe.data.ps.observation.Catch.meanWeight.validation.notFilled=Debe seleccionar uno de los dos valores (peso medio o talla media).
    
    1288 1288
     observe.data.ps.observation.Catch.meanWeightComputed.computed.tip=El peso medio se calculó
    
    1289 1289
     observe.data.ps.observation.Catch.meanWeightComputed.observed.tip=El peso medio se observó
    
    1290
    +observe.data.ps.observation.Catch.minMaxWeight=Lower / upper weight limit (in kg) TODO
    
    1290 1291
     observe.data.ps.observation.Catch.minWeight=Lower weight limit (in kg) TODO
    
    1291 1292
     observe.data.ps.observation.Catch.minWeight.short=Max weight (in kg)
    
    1292 1293
     observe.data.ps.observation.Catch.reasonForDiscard=Razón del descarte
    

  • core/services/i18n/src/main/i18n/translations/services_fr_FR.properties
    ... ... @@ -1287,6 +1287,7 @@ observe.data.ps.observation.Catch.meanWeight.short=Poids moy
    1287 1287
     observe.data.ps.observation.Catch.meanWeight.validation.notFilled=Une des deux valeurs (poids moyen ou taille moyenne) devrait être renseignée.
    
    1288 1288
     observe.data.ps.observation.Catch.meanWeightComputed.computed.tip=Le poids moyen a été calculé (%s)
    
    1289 1289
     observe.data.ps.observation.Catch.meanWeightComputed.observed.tip=Le poids moyen a été observé
    
    1290
    +observe.data.ps.observation.Catch.minMaxWeight=Borne de poids inférieure / supérieure (en kg)
    
    1290 1291
     observe.data.ps.observation.Catch.minWeight=Borne de poids inférieure (en kg)
    
    1291 1292
     observe.data.ps.observation.Catch.minWeight.short=Poids min (en kg)
    
    1292 1293
     observe.data.ps.observation.Catch.reasonForDiscard=Raison rejet
    

  • core/services/test/src/main/resources/fixtures/fr/ird/observe/services/service/ValidateService-dataResult.json
    ... ... @@ -43828,7 +43828,7 @@
    43828 43828
                 "topiaVersion": 16,
    
    43829 43829
                 "topiaCreateDate": "2009-04-15T00:00:00.009Z"
    
    43830 43830
               },
    
    43831
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    43831
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    43832 43832
               "catchWeight": 1.0,
    
    43833 43833
               "well": "2",
    
    43834 43834
               "id": "fr.ird.data.ps.observation.Catch#1554060786914#0.3899957341641852",
    
    ... ... @@ -43874,7 +43874,7 @@
    43874 43874
                 "topiaVersion": 16,
    
    43875 43875
                 "topiaCreateDate": "2009-04-15T00:00:00.004Z"
    
    43876 43876
               },
    
    43877
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    43877
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    43878 43878
               "catchWeight": 1.0,
    
    43879 43879
               "well": "2",
    
    43880 43880
               "id": "fr.ird.data.ps.observation.Catch#1554060786914#0.455212337619455",
    
    ... ... @@ -43920,7 +43920,7 @@
    43920 43920
                 "topiaVersion": 16,
    
    43921 43921
                 "topiaCreateDate": "2009-04-15T00:00:00.010Z"
    
    43922 43922
               },
    
    43923
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    43923
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    43924 43924
               "catchWeight": 16.0,
    
    43925 43925
               "well": "1",
    
    43926 43926
               "id": "fr.ird.data.ps.observation.Catch#1554228692388#0.40195828823649804",
    
    ... ... @@ -43966,7 +43966,7 @@
    43966 43966
                 "topiaVersion": 15,
    
    43967 43967
                 "topiaCreateDate": "2009-04-15T00:00:00.001Z"
    
    43968 43968
               },
    
    43969
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    43969
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    43970 43970
               "catchWeight": 1.0,
    
    43971 43971
               "well": "1",
    
    43972 43972
               "id": "fr.ird.data.ps.observation.Catch#1554228692388#0.5827043409961202",
    
    ... ... @@ -44012,7 +44012,7 @@
    44012 44012
                 "topiaVersion": 15,
    
    44013 44013
                 "topiaCreateDate": "2009-04-15T00:00:00.001Z"
    
    44014 44014
               },
    
    44015
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44015
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44016 44016
               "catchWeight": 4.0,
    
    44017 44017
               "well": "1",
    
    44018 44018
               "id": "fr.ird.data.ps.observation.Catch#1554228964667#0.3873882731438876",
    
    ... ... @@ -44058,7 +44058,7 @@
    44058 44058
                 "topiaVersion": 16,
    
    44059 44059
                 "topiaCreateDate": "2009-04-15T00:00:00.010Z"
    
    44060 44060
               },
    
    44061
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44061
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44062 44062
               "catchWeight": 27.0,
    
    44063 44063
               "well": "1",
    
    44064 44064
               "id": "fr.ird.data.ps.observation.Catch#1554228964667#0.6898347092973715",
    
    ... ... @@ -44104,7 +44104,7 @@
    44104 44104
                 "topiaVersion": 15,
    
    44105 44105
                 "topiaCreateDate": "2009-04-15T00:00:00.001Z"
    
    44106 44106
               },
    
    44107
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44107
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44108 44108
               "catchWeight": 1.0,
    
    44109 44109
               "well": "4",
    
    44110 44110
               "id": "fr.ird.data.ps.observation.Catch#1554228964683#0.5525193499129678",
    
    ... ... @@ -44150,7 +44150,7 @@
    44150 44150
                 "topiaVersion": 16,
    
    44151 44151
                 "topiaCreateDate": "2009-04-15T00:00:00.010Z"
    
    44152 44152
               },
    
    44153
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44153
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44154 44154
               "catchWeight": 39.0,
    
    44155 44155
               "well": "4",
    
    44156 44156
               "id": "fr.ird.data.ps.observation.Catch#1554228964683#0.6111969202426193",
    
    ... ... @@ -44196,7 +44196,7 @@
    44196 44196
                 "topiaVersion": 16,
    
    44197 44197
                 "topiaCreateDate": "2009-04-15T00:00:00.010Z"
    
    44198 44198
               },
    
    44199
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44199
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44200 44200
               "catchWeight": 15.0,
    
    44201 44201
               "well": "4",
    
    44202 44202
               "id": "fr.ird.data.ps.observation.Catch#1554229020077#0.06929838028483837",
    
    ... ... @@ -44242,7 +44242,7 @@
    44242 44242
                 "topiaVersion": 16,
    
    44243 44243
                 "topiaCreateDate": "2009-04-15T00:00:00.010Z"
    
    44244 44244
               },
    
    44245
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44245
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44246 44246
               "catchWeight": 25.0,
    
    44247 44247
               "well": "2",
    
    44248 44248
               "id": "fr.ird.data.ps.observation.Catch#1554229020077#0.764944972601716",
    
    ... ... @@ -44288,7 +44288,7 @@
    44288 44288
                 "topiaVersion": 15,
    
    44289 44289
                 "topiaCreateDate": "2009-04-15T00:00:00.001Z"
    
    44290 44290
               },
    
    44291
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44291
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44292 44292
               "catchWeight": 1.0,
    
    44293 44293
               "well": "3",
    
    44294 44294
               "id": "fr.ird.data.ps.observation.Catch#1554659569269#0.5089206009917716",
    
    ... ... @@ -44334,7 +44334,7 @@
    44334 44334
                 "topiaVersion": 16,
    
    44335 44335
                 "topiaCreateDate": "2009-04-15T00:00:00.010Z"
    
    44336 44336
               },
    
    44337
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44337
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44338 44338
               "catchWeight": 53.0,
    
    44339 44339
               "well": "3",
    
    44340 44340
               "id": "fr.ird.data.ps.observation.Catch#1554659569269#0.9595940690443661",
    
    ... ... @@ -44470,7 +44470,7 @@
    44470 44470
                 "topiaVersion": 19,
    
    44471 44471
                 "topiaCreateDate": "2009-04-15T00:00:00.005Z"
    
    44472 44472
               },
    
    44473
    -          "speciesFateLabel": "Conservé (en cuve, poisson séché ou salé)",
    
    44473
    +          "speciesFateLabel": "Conservé à destination de la conserverie",
    
    44474 44474
               "catchWeight": 12.0,
    
    44475 44475
               "well": "3T",
    
    44476 44476
               "id": "fr.ird.data.ps.observation.Catch#1612860304046#0.051529228859696796",
    

  • core/services/test/src/main/resources/fixtures/fr/ird/observe/services/service/ValidateService-referentialResult.json
    ... ... @@ -56940,13 +56940,13 @@
    56940 56940
             },
    
    56941 56941
             {
    
    56942 56942
               "fieldName": "uri",
    
    56943
    -          "scope": "WARNING",
    
    56944
    -          "message": "Le champ n\u0027est pas renseigné."
    
    56943
    +          "scope": "ERROR",
    
    56944
    +          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    56945 56945
             },
    
    56946 56946
             {
    
    56947 56947
               "fieldName": "uri",
    
    56948
    -          "scope": "ERROR",
    
    56949
    -          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    56948
    +          "scope": "WARNING",
    
    56949
    +          "message": "Le champ n\u0027est pas renseigné."
    
    56950 56950
             },
    
    56951 56951
             {
    
    56952 56952
               "fieldName": "wormsId",
    
    ... ... @@ -62791,13 +62791,13 @@
    62791 62791
             },
    
    62792 62792
             {
    
    62793 62793
               "fieldName": "uri",
    
    62794
    -          "scope": "WARNING",
    
    62795
    -          "message": "Le champ n\u0027est pas renseigné."
    
    62794
    +          "scope": "ERROR",
    
    62795
    +          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    62796 62796
             },
    
    62797 62797
             {
    
    62798 62798
               "fieldName": "uri",
    
    62799
    -          "scope": "ERROR",
    
    62800
    -          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    62799
    +          "scope": "WARNING",
    
    62800
    +          "message": "Le champ n\u0027est pas renseigné."
    
    62801 62801
             },
    
    62802 62802
             {
    
    62803 62803
               "fieldName": "wormsId",
    
    ... ... @@ -63241,13 +63241,13 @@
    63241 63241
           "messages": [
    
    63242 63242
             {
    
    63243 63243
               "fieldName": "uri",
    
    63244
    -          "scope": "WARNING",
    
    63245
    -          "message": "Le champ n\u0027est pas renseigné."
    
    63244
    +          "scope": "ERROR",
    
    63245
    +          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    63246 63246
             },
    
    63247 63247
             {
    
    63248 63248
               "fieldName": "uri",
    
    63249
    -          "scope": "ERROR",
    
    63250
    -          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    63249
    +          "scope": "WARNING",
    
    63250
    +          "message": "Le champ n\u0027est pas renseigné."
    
    63251 63251
             },
    
    63252 63252
             {
    
    63253 63253
               "fieldName": "wormsId",
    
    ... ... @@ -68238,12 +68238,12 @@
    68238 68238
             {
    
    68239 68239
               "fieldName": "species",
    
    68240 68240
               "scope": "ERROR",
    
    68241
    -          "message": "Le référentiel sélectionné «SPY - Sphyrnidae - Famille Sphyrnidae» (à la position 24) est désactivé."
    
    68241
    +          "message": "Le référentiel sélectionné «LKY - Lepidochelys kempii - Tortue de Kemp» (à la position 120) est désactivé."
    
    68242 68242
             },
    
    68243 68243
             {
    
    68244 68244
               "fieldName": "species",
    
    68245 68245
               "scope": "ERROR",
    
    68246
    -          "message": "Le référentiel sélectionné «LKY - Lepidochelys kempii - Tortue de Kemp» (à la position 120) est désactivé."
    
    68246
    +          "message": "Le référentiel sélectionné «SPY - Sphyrnidae - Famille Sphyrnidae» (à la position 24) est désactivé."
    
    68247 68247
             },
    
    68248 68248
             {
    
    68249 68249
               "fieldName": "species",
    
    ... ... @@ -68504,7 +68504,7 @@
    68504 68504
             {
    
    68505 68505
               "fieldName": "species",
    
    68506 68506
               "scope": "ERROR",
    
    68507
    -          "message": "Le référentiel sélectionné «SPY - Sphyrnidae - Famille Sphyrnidae» (à la position 24) est désactivé."
    
    68507
    +          "message": "Le référentiel sélectionné «LKY - Lepidochelys kempii - Tortue de Kemp» (à la position 120) est désactivé."
    
    68508 68508
             },
    
    68509 68509
             {
    
    68510 68510
               "fieldName": "species",
    
    ... ... @@ -68514,7 +68514,7 @@
    68514 68514
             {
    
    68515 68515
               "fieldName": "species",
    
    68516 68516
               "scope": "ERROR",
    
    68517
    -          "message": "Le référentiel sélectionné «LKY - Lepidochelys kempii - Tortue de Kemp» (à la position 120) est désactivé."
    
    68517
    +          "message": "Le référentiel sélectionné «SPY - Sphyrnidae - Famille Sphyrnidae» (à la position 24) est désactivé."
    
    68518 68518
             },
    
    68519 68519
             {
    
    68520 68520
               "fieldName": "species",
    
    ... ... @@ -142383,13 +142383,13 @@
    142383 142383
             },
    
    142384 142384
             {
    
    142385 142385
               "fieldName": "uri",
    
    142386
    -          "scope": "WARNING",
    
    142387
    -          "message": "Le champ n\u0027est pas renseigné."
    
    142386
    +          "scope": "ERROR",
    
    142387
    +          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    142388 142388
             },
    
    142389 142389
             {
    
    142390 142390
               "fieldName": "uri",
    
    142391
    -          "scope": "ERROR",
    
    142392
    -          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    142391
    +          "scope": "WARNING",
    
    142392
    +          "message": "Le champ n\u0027est pas renseigné."
    
    142393 142393
             },
    
    142394 142394
             {
    
    142395 142395
               "fieldName": "wellRegex",
    
    ... ... @@ -157800,13 +157800,13 @@
    157800 157800
             },
    
    157801 157801
             {
    
    157802 157802
               "fieldName": "uri",
    
    157803
    -          "scope": "WARNING",
    
    157804
    -          "message": "Le champ n\u0027est pas renseigné."
    
    157803
    +          "scope": "ERROR",
    
    157804
    +          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    157805 157805
             },
    
    157806 157806
             {
    
    157807 157807
               "fieldName": "uri",
    
    157808
    -          "scope": "ERROR",
    
    157809
    -          "message": "Le champ (s\u0027il est renseigné) ne doit pas être consituté que d\u0027espaces."
    
    157808
    +          "scope": "WARNING",
    
    157809
    +          "message": "Le champ n\u0027est pas renseigné."
    
    157810 157810
             },
    
    157811 157811
             {
    
    157812 157812
               "fieldName": "vesselSizeCategory",
    
    ... ... @@ -196593,6 +196593,7 @@
    196593 196593
               "code": "1",
    
    196594 196594
               "label": "Echappe du filet (pour requin-baleine et cétacés)",
    
    196595 196595
               "discard": true,
    
    196596
    +          "weightRangeAllowed": false,
    
    196596 196597
               "needComment": false,
    
    196597 196598
               "enabled": true,
    
    196598 196599
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683618#0.06155887805368032",
    
    ... ... @@ -196626,6 +196627,7 @@
    196626 196627
               "code": "3",
    
    196627 196628
               "label": "Sortie mort du filet (pour requin-baleine et cétacés)",
    
    196628 196629
               "discard": true,
    
    196630
    +          "weightRangeAllowed": false,
    
    196629 196631
               "needComment": false,
    
    196630 196632
               "enabled": true,
    
    196631 196633
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683619#0.11883784875534997",
    
    ... ... @@ -196659,6 +196661,7 @@
    196659 196661
               "code": "4",
    
    196660 196662
               "label": "Rejeté vivant",
    
    196661 196663
               "discard": true,
    
    196664
    +          "weightRangeAllowed": false,
    
    196662 196665
               "needComment": false,
    
    196663 196666
               "enabled": true,
    
    196664 196667
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683619#0.5308862132841506",
    
    ... ... @@ -196682,6 +196685,7 @@
    196682 196685
               "code": "6",
    
    196683 196686
               "label": "Conservé à destination de la conserverie",
    
    196684 196687
               "discard": false,
    
    196688
    +          "weightRangeAllowed": true,
    
    196685 196689
               "needComment": false,
    
    196686 196690
               "enabled": true,
    
    196687 196691
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683619#0.5722739932065866",
    
    ... ... @@ -196710,6 +196714,7 @@
    196710 196714
               "code": "5",
    
    196711 196715
               "label": "Rejeté mort",
    
    196712 196716
               "discard": true,
    
    196717
    +          "weightRangeAllowed": true,
    
    196713 196718
               "needComment": false,
    
    196714 196719
               "enabled": true,
    
    196715 196720
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683619#0.6250731662108877",
    
    ... ... @@ -196733,6 +196738,7 @@
    196733 196738
               "code": "2",
    
    196734 196739
               "label": "Sortie vivant du filet (pour requin-baleine et cétacés)",
    
    196735 196740
               "discard": true,
    
    196741
    +          "weightRangeAllowed": false,
    
    196736 196742
               "needComment": false,
    
    196737 196743
               "enabled": true,
    
    196738 196744
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683619#0.9931091059863436",
    
    ... ... @@ -196765,6 +196771,7 @@
    196765 196771
             "content": {
    
    196766 196772
               "code": "7",
    
    196767 196773
               "label": "Partiellement conservé (ex: ailerons de requin, poisson séché)",
    
    196774
    +          "weightRangeAllowed": false,
    
    196768 196775
               "needComment": false,
    
    196769 196776
               "enabled": false,
    
    196770 196777
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683620#0.46609703818634485",
    
    ... ... @@ -196803,6 +196810,7 @@
    196803 196810
               "code": "8",
    
    196804 196811
               "label": "Utilisé en cuisine du bord",
    
    196805 196812
               "discard": false,
    
    196813
    +          "weightRangeAllowed": false,
    
    196806 196814
               "needComment": false,
    
    196807 196815
               "enabled": true,
    
    196808 196816
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683621#0.6728026426066158",
    
    ... ... @@ -196835,6 +196843,7 @@
    196835 196843
             "content": {
    
    196836 196844
               "code": "9",
    
    196837 196845
               "label": "Autres (à préciser dans les notes)",
    
    196846
    +          "weightRangeAllowed": false,
    
    196838 196847
               "needComment": true,
    
    196839 196848
               "enabled": true,
    
    196840 196849
               "id": "fr.ird.referential.ps.common.SpeciesFate#1239832683621#0.9099804284263154",
    
    ... ... @@ -196868,6 +196877,7 @@
    196868 196877
               "code": "15",
    
    196869 196878
               "label": "Conservé pour le marché local ou poisson séché/salé à bord",
    
    196870 196879
               "discard": false,
    
    196880
    +          "weightRangeAllowed": false,
    
    196871 196881
               "needComment": false,
    
    196872 196882
               "enabled": true,
    
    196873 196883
               "id": "fr.ird.referential.ps.common.SpeciesFate#1464000000000#15",
    
    ... ... @@ -196895,6 +196905,7 @@
    196895 196905
             "content": {
    
    196896 196906
               "code": "10",
    
    196897 196907
               "label": "Ailerons seulements",
    
    196908
    +          "weightRangeAllowed": false,
    
    196898 196909
               "needComment": false,
    
    196899 196910
               "enabled": true,
    
    196900 196911
               "id": "fr.ird.referential.ps.common.SpeciesFate#1467372855729#0.568287924081734",
    
    ... ... @@ -196918,6 +196929,7 @@
    196918 196929
               "code": "11",
    
    196919 196930
               "label": "Rejeté, statut non observé",
    
    196920 196931
               "discard": true,
    
    196932
    +          "weightRangeAllowed": false,
    
    196921 196933
               "needComment": false,
    
    196922 196934
               "enabled": true,
    
    196923 196935
               "id": "fr.ird.referential.ps.common.SpeciesFate#1501492537510#0.9210847837998154",
    
    ... ... @@ -196941,6 +196953,7 @@
    196941 196953
               "code": "12",
    
    196942 196954
               "label": "Conservé pour raisons scientifiques",
    
    196943 196955
               "discard": false,
    
    196956
    +          "weightRangeAllowed": false,
    
    196944 196957
               "needComment": false,
    
    196945 196958
               "enabled": true,
    
    196946 196959
               "id": "fr.ird.referential.ps.common.SpeciesFate#1501492831539#0.9377232562184147",
    
    ... ... @@ -196964,6 +196977,7 @@
    196964 196977
               "code": "13",
    
    196965 196978
               "label": "Rejeté suffocant",
    
    196966 196979
               "discard": true,
    
    196980
    +          "weightRangeAllowed": false,
    
    196967 196981
               "needComment": false,
    
    196968 196982
               "enabled": true,
    
    196969 196983
               "id": "fr.ird.referential.ps.common.SpeciesFate#1544448835551#0.620629930572886",
    
    ... ... @@ -196987,6 +197001,7 @@
    196987 197001
               "code": "14",
    
    196988 197002
               "label": "Rejeté suffocant blessé",
    
    196989 197003
               "discard": true,
    
    197004
    +          "weightRangeAllowed": false,
    
    196990 197005
               "needComment": false,
    
    196991 197006
               "enabled": true,
    
    196992 197007
               "id": "fr.ird.referential.ps.common.SpeciesFate#1544448977865#0.24265421995390768",
    

  • model/src/main/models/Observe/dto/class/i18nLabels.properties
    ... ... @@ -84,7 +84,7 @@ data.ps.logbook.Well=well,wellVessel,wellFactory,wellSamplingConformity,wellSamp
    84 84
     data.ps.logbook.WellActivity=activity,wellActivitySpecies
    
    85 85
     data.ps.logbook.WellActivitySpecies=species,weight,weightCategory,count,setSpeciesNumber
    
    86 86
     data.ps.observation.Activity=date,coordinate,observedSystem.available,observedSystem.selected,comment,comment2,currentFpaZone,dataQuality,detectionMode,ersId,floatingObjectEmpty,latitude,longitude,nextFpaZone,nonTargetCatchSpecies,observedSystem,observedSystemDistance,previousFpaZone,quadrant,reasonForNoFishing,seaSurfaceTemperature,surroundingActivity,time,vesselActivity,vesselSpeed,wind,generalTab,error.no.activity.6,measurementsTab,observedSystemTab
    
    87
    -data.ps.observation.Catch=catchWeight,comment,informationSource,lengthMeasureMethod,meanLength,minWeight,maxWeight,meanWeight,reasonForDiscard,species,speciesFate,totalCount,weightMeasureMethod,well,catchWeightComputed.computed.tip,catchWeightComputed.observed.tip,meanLengthComputed.computed.tip,meanLengthComputed.observed.tip,meanWeightComputed.computed.tip,meanWeightComputed.observed.tip,totalCountComputed.computed.tip,totalCountComputed.observed.tip
    
    87
    +data.ps.observation.Catch=catchWeight,comment,informationSource,lengthMeasureMethod,meanLength,minWeight,maxWeight,meanWeight,minMaxWeight,reasonForDiscard,species,speciesFate,totalCount,weightMeasureMethod,well,catchWeightComputed.computed.tip,catchWeightComputed.observed.tip,meanLengthComputed.computed.tip,meanLengthComputed.observed.tip,meanWeightComputed.computed.tip,meanWeightComputed.observed.tip,totalCountComputed.computed.tip,totalCountComputed.observed.tip
    
    88 88
     data.ps.observation.FloatingObject=materialsValid,objectOperation,supportVesselName,country,vessel,computedBiodegradable,computedNonEntangling,computedSimplifiedObjectType,computedValues,generalTab,buoysTab,materialsTab,notComputed,type.short
    
    89 89
     data.ps.observation.NonTargetCatchRelease=comment,conformity,count,length,lengthMeasureMethod,releasingTime,sex,status,species,speciesGroupReleaseMode,message.cantAdd
    
    90 90
     data.ps.observation.ObjectObservedSpecies=count,species,speciesStatus
    

  • model/src/main/models/Observe/dto/class/i18nOverrideLabels.properties
    ... ... @@ -23,7 +23,7 @@ data.ll.common.Trip=species
    23 23
     data.ll.landing.Landing=vessel
    
    24 24
     data.ps.localmarket.Sample=well
    
    25 25
     data.ps.logbook.Catch=weightMeasureMethod.validation.required
    
    26
    -data.ps.observation.Catch=minWeight,maxWeight,weightMeasureMethod
    
    26
    +data.ps.observation.Catch=minWeight,maxWeight,minMaxWeight,weightMeasureMethod
    
    27 27
     data.ps.observation.SchoolEstimate=species
    
    28 28
     data.ps.observation.Set=startTime,haulingStartTimeStamp,haulingEndTimeStamp,endTimeStamp
    
    29 29
     referential.common.Species=codeAndHomeId

  • toolkit/api/src/main/java/fr/ird/observe/dto/StringCleaner.java
    1
    +package fr.ird.observe.dto;
    
    2
    +
    
    3
    +/*-
    
    4
    + * #%L
    
    5
    + * ObServe Toolkit :: API
    
    6
    + * %%
    
    7
    + * Copyright (C) 2008 - 2022 IRD, Ultreia.io
    
    8
    + * %%
    
    9
    + * This program is free software: you can redistribute it and/or modify
    
    10
    + * it under the terms of the GNU General Public License as
    
    11
    + * published by the Free Software Foundation, either version 3 of the
    
    12
    + * License, or (at your option) any later version.
    
    13
    + *
    
    14
    + * This program is distributed in the hope that it will be useful,
    
    15
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    16
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    
    17
    + * GNU General Public License for more details.
    
    18
    + *
    
    19
    + * You should have received a copy of the GNU General Public
    
    20
    + * License along with this program.  If not, see
    
    21
    + * <http://www.gnu.org/licenses/gpl-3.0.html>.
    
    22
    + * #L%
    
    23
    + */
    
    24
    +
    
    25
    +import java.util.function.Function;
    
    26
    +
    
    27
    +/**
    
    28
    + * Object to clean a string related to a database field.
    
    29
    + * <p>
    
    30
    + * Created on 12/11/2022.
    
    31
    + *
    
    32
    + * @author Tony Chemit - dev@tchemit.fr
    
    33
    + * @since 9.017
    
    34
    + */
    
    35
    +public class StringCleaner implements Function<String, String> {
    
    36
    +
    
    37
    +    public static final StringCleaner ALL = new StringCleaner(true, true, true);
    
    38
    +    public static final StringCleaner REMOVE_SINGLE_QUOTE_AND_TRIM = new StringCleaner(true, true, false);
    
    39
    +    public static final StringCleaner TRIM_AND_REPLACE_EMPTY_BY_NULL = new StringCleaner(false, true, true);
    
    40
    +    public static final StringCleaner TRIM = new StringCleaner(false, true, false);
    
    41
    +
    
    42
    +    /**
    
    43
    +     * To remove any single quote in given string.
    
    44
    +     */
    
    45
    +    private final boolean removeSingleQuote;
    
    46
    +    /**
    
    47
    +     * To perform a trim on given string.
    
    48
    +     */
    
    49
    +    private final boolean trim;
    
    50
    +    /**
    
    51
    +     * To replace the given string value by null if it is empty.
    
    52
    +     */
    
    53
    +    private final boolean replaceEmptyByNull;
    
    54
    +
    
    55
    +    public StringCleaner(boolean removeSingleQuote, boolean trim, boolean replaceEmptyByNull) {
    
    56
    +        this.removeSingleQuote = removeSingleQuote;
    
    57
    +        this.trim = trim;
    
    58
    +        this.replaceEmptyByNull = replaceEmptyByNull;
    
    59
    +    }
    
    60
    +
    
    61
    +    public static String removeSingleQuote(String string) {
    
    62
    +        return string.replaceAll("'", "");
    
    63
    +    }
    
    64
    +
    
    65
    +    @Override
    
    66
    +    public String apply(String string) {
    
    67
    +        if (string == null) {
    
    68
    +            return null;
    
    69
    +        }
    
    70
    +        String result = string;
    
    71
    +        if (removeSingleQuote) {
    
    72
    +            result = removeSingleQuote(result);
    
    73
    +        }
    
    74
    +        if (trim) {
    
    75
    +            result = result.trim();
    
    76
    +        }
    
    77
    +        if (replaceEmptyByNull && result.isEmpty()) {
    
    78
    +            result = null;
    
    79
    +        }
    
    80
    +        return result;
    
    81
    +    }
    
    82
    +}

  • toolkit/api/src/main/java/fr/ird/observe/persistence/SqlHelper.java
    ... ... @@ -64,7 +64,21 @@ public class SqlHelper {
    64 64
             if (trim.length() > maxLength) {
    
    65 65
                 trim = trim.substring(0, maxLength - 1);
    
    66 66
             }
    
    67
    -        return "'" + trim.replaceAll("'", "''") + "'";
    
    67
    +        return "'" + escapeSingleQuote(trim) + "'";
    
    68 68
         }
    
    69 69
     
    
    70
    +    public static String escapeSingleQuote(String string) {
    
    71
    +        return string.replaceAll("'", "''");
    
    72
    +    }
    
    73
    +
    
    74
    +    public static String escapeString(String string) {
    
    75
    +        if (string == null) {
    
    76
    +            return "NULL";
    
    77
    +        }
    
    78
    +        String trim = string.trim();
    
    79
    +        if (trim.isEmpty()) {
    
    80
    +            return "NULL";
    
    81
    +        }
    
    82
    +        return "'" + escapeSingleQuote(trim) + "'";
    
    83
    +    }
    
    70 84
     }

  • toolkit/persistence/src/main/java/fr/ird/observe/spi/context/DataDtoEntityContext.java
    ... ... @@ -35,6 +35,7 @@ import fr.ird.observe.dto.referential.ReferentialLocale;
    35 35
     import fr.ird.observe.entities.Entity;
    
    36 36
     import fr.ird.observe.entities.data.DataEntity;
    
    37 37
     import fr.ird.observe.entities.data.DataFileAware;
    
    38
    +import fr.ird.observe.persistence.SqlHelper;
    
    38 39
     import fr.ird.observe.persistence.request.DeleteRequest;
    
    39 40
     import fr.ird.observe.spi.service.ServiceContext;
    
    40 41
     import fr.ird.observe.spi.usage.UsageHelper;
    
    ... ... @@ -78,14 +79,7 @@ public abstract class DataDtoEntityContext<
    78 79
         }
    
    79 80
     
    
    80 81
         public static String toId(Entity entity) {
    
    81
    -        return entity == null ? "NULL" : escapeString(entity.getTopiaId());
    
    82
    -    }
    
    83
    -
    
    84
    -    public static String escapeString(String string) {
    
    85
    -        if (string == null) {
    
    86
    -            return "NULL";
    
    87
    -        }
    
    88
    -        return "'" + string.trim() + "'";
    
    82
    +        return entity == null ? "NULL" : SqlHelper.escapeString(entity.getTopiaId());
    
    89 83
         }
    
    90 84
     
    
    91 85
         public static Blob byteArrayToBlob(byte[] bytes) {