Tony CHEMIT pushed to branch develop at ultreiaio / ird-observe
Commits:
-
7ea06d73
by Tony Chemit at 2022-11-12T14:43:10+01:00
-
8f5e68fb
by Tony Chemit at 2022-11-12T16:10:50+01:00
-
c7278943
by Tony Chemit at 2022-11-12T16:10:50+01:00
-
247c8c3d
by Tony Chemit at 2022-11-12T16:10:50+01:00
20 changed files:
- client/datasource/editor/ps/src/main/i18n/getters/jaxx.getter
- client/datasource/editor/ps/src/main/java/fr/ird/observe/client/datasource/editor/ps/data/observation/SetCatchUI.jaxx
- core/api/services/src/main/i18n/getters/labels.getter
- core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/common/TripSpi.java
- core/persistence/resources/src/main/java/fr/ird/observe/persistence/avdth/data/DataWriter.java
- core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/DataSourceMigrationForVersion_9_0.java
- core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/DiscardedTargetCatchRecord.java
- + core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/FixCommentHelper.java
- + core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/FixStringHelper.java
- core/persistence/resources/src/main/java/fr/ird/observe/spi/migration/v9/NotDiscardedTargetCatchRecord.java
- core/services/i18n/src/main/i18n/translations/services_en_GB.properties
- core/services/i18n/src/main/i18n/translations/services_es_ES.properties
- core/services/i18n/src/main/i18n/translations/services_fr_FR.properties
- core/services/test/src/main/resources/fixtures/fr/ird/observe/services/service/ValidateService-dataResult.json
- core/services/test/src/main/resources/fixtures/fr/ird/observe/services/service/ValidateService-referentialResult.json
- model/src/main/models/Observe/dto/class/i18nLabels.properties
- model/src/main/models/Observe/dto/class/i18nOverrideLabels.properties
- + toolkit/api/src/main/java/fr/ird/observe/dto/StringCleaner.java
- toolkit/api/src/main/java/fr/ird/observe/persistence/SqlHelper.java
- toolkit/persistence/src/main/java/fr/ird/observe/spi/context/DataDtoEntityContext.java
Changes:
| ... | ... | @@ -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
|
| ... | ... | @@ -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>
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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 |
| ... | ... | @@ -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) {
|
| ... | ... | @@ -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 | }
|
| ... | ... | @@ -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 | } |
| 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 | +} |
| 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 | +} |
| ... | ... | @@ -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 | } |
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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",
|
| ... | ... | @@ -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",
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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 |
| 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 | +} |
| ... | ... | @@ -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 | } |
| ... | ... | @@ -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) {
|