Tony CHEMIT pushed to branch develop at ultreiaio / ird-observe Commits: de9f80df by Tony Chemit at 2024-05-22T10:27:28+02:00 Introduce EntityInterceptorCallback and use it in API - - - - - 43955452 by Tony Chemit at 2024-05-22T10:27:28+02:00 Implements some EntityInterceptorCallback on editable entities to custom how to load dto for validation (without using the database) - - - - - 93664ef5 by Tony Chemit at 2024-05-22T10:27:28+02:00 Remove redundant code in preCreate method and remove super.loadDtoForValidation(context, parent, entity, dto) calls - - - - - e7f98efe by Tony Chemit at 2024-05-22T10:27:34+02:00 Implements some EntityInterceptorCallback on openable entities to custom how to load dto for validation (without using the database) - - - - - 629f25bb by Tony Chemit at 2024-05-22T10:27:34+02:00 Remove ignored tests in DataEntityServiceLocalWriteTest - - - - - 7024b23b by Tony Chemit at 2024-05-22T10:27:34+02:00 Add new test in DataEntityServiceLocalWriteTest to check issue is now ok. - - - - - af5d2837 by Tony Chemit at 2024-05-22T10:48:55+02:00 Merge branch 'feature/issue-2886' into develop Insertion de set LL logbook sans capture - Closes #2886 - - - - - 27 changed files: - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/common/TripSpi.java - + core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/logbook/SetInterceptorCallback.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/logbook/SetSpi.java - + core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/observation/SetInterceptorCallback.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/observation/SetSpi.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/common/TripBatchSpi.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/common/TripSpi.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/localmarket/SurveySpi.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/logbook/ActivitySpi.java - + core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/logbook/SampleInterceptorCallback.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/logbook/SampleSpi.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/RouteSpi.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/SampleSpi.java - + core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/SetInterceptorCallback.java - core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/SetSpi.java - core/services/local/src/test/java/fr/ird/observe/services/local/service/api/DataEntityServiceLocalWriteTest.java - + core/services/test/src/main/resources/fixtures/fr/ird/observe/services/service/data/ll/common/TripService-issue2886.json - toolkit/persistence/src/main/java/fr/ird/observe/spi/context/EditableDtoEntityContext.java - toolkit/persistence/src/main/java/fr/ird/observe/spi/context/OpenableDtoEntityContext.java - toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/EntityInterceptor.java - toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/EntityInterceptors.java - toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/ValidationMessageDetector.java - + toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/DefaultEntityInterceptorCallback.java - + toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/EdiableEntityInterceptorCallback.java - + toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/EntityInterceptorCallback.java - + toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/EntityInterceptorCallbacks.java - + toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/OpenableEntityInterceptorCallback.java Changes: ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/common/TripSpi.java ===================================== @@ -98,7 +98,6 @@ public class TripSpi extends GeneratedTripSpi { @Override public void loadDtoForValidation(ServiceContext context, Trip entity, TripDto dto) { - super.loadDtoForValidation(context, entity, dto); if (dto.getEndDate() == null) { Date date = Dates.getEndOfDay(context.now()); dto.setEndDate(date); ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/logbook/SetInterceptorCallback.java ===================================== @@ -0,0 +1,56 @@ +package fr.ird.observe.entities.data.ll.logbook; + +/*- + * #%L + * ObServe Core :: Persistence :: Java + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.auto.service.AutoService; +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.dto.data.ll.logbook.SetDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.entities.data.ll.common.Trip; +import fr.ird.observe.spi.service.ServiceContext; +import fr.ird.observe.spi.validation.callback.EntityInterceptorCallback; + +import java.util.Deque; + +/** + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.3.4 + */ +@SuppressWarnings("rawtypes") +@AutoService(EntityInterceptorCallback.class) +public class SetInterceptorCallback implements EntityInterceptorCallback<SetDto, Set, SetSpi> { + + @Override + public boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType) { + return Set.class.equals(entityType); + } + + @Override + public void loadDtoForValidation(ServiceContext context, Deque<Entity> path, SetSpi spi, Set set, SetDto dto) { + Trip trip = (Trip) path.getFirst(); + Activity activity = EntityInterceptorCallback.getParent(path, set, Activity.class); + spi.loadDtoForValidation(context, trip, activity, dto); + } +} ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/logbook/SetSpi.java ===================================== @@ -72,21 +72,28 @@ public class SetSpi extends GeneratedSetSpi { preCreated.setLightsticksUsed(false); // by default (See https://gitlab.com/ultreiaio/ird-observe/-/issues/2685) preCreated.setMonitored(false); - Form<SetDto> form = super.preCreate(context, parent, preCreated); - form.getObject().setOtherSets(getBrothers(context, parent)); - return form; + //FIXME super.preCreate does already this? +// Form<SetDto> form = super.preCreate(context, parent, preCreated); +// form.getObject().setOtherSets(getBrothers(context, parent)); + return super.preCreate(context, parent, preCreated); } @Override public void loadDtoForValidation(ServiceContext context, Activity parent, Set entity, SetDto dto) { - super.loadDtoForValidation(context, parent, entity, dto); dto.setOtherSets(getBrothers(context, parent)); } + public void loadDtoForValidation(ServiceContext context, Trip trip, Activity parent, SetDto dto) { + dto.setOtherSets(getBrothers(context.getReferentialLocale(), parent, trip)); + } + public java.util.Set<SetStubDto> getBrothers(ServiceContext context, Activity parent) { - java.util.Set<SetStubDto> result = new HashSet<>(); - ReferentialLocale referentialLocale = context.getReferentialLocale(); Trip trip = Activity.SPI.getParent(context, parent.getTopiaId()); + return getBrothers(context.getReferentialLocale(), parent, trip); + } + + private java.util.Set<SetStubDto> getBrothers(ReferentialLocale referentialLocale, Activity parent, Trip trip) { + java.util.Set<SetStubDto> result = new HashSet<>(); trip.getActivityLogbook().stream().filter(a -> a.getVesselActivity().isAllowSet() && !Objects.equals(a, parent) && a.getSet() != null).forEach( oneParent -> { Set otherSet = oneParent.getSet(); ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/observation/SetInterceptorCallback.java ===================================== @@ -0,0 +1,57 @@ +package fr.ird.observe.entities.data.ll.observation; + +/*- + * #%L + * ObServe Core :: Persistence :: Java + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.auto.service.AutoService; +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.dto.data.ll.observation.SetDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.entities.data.ll.common.Trip; +import fr.ird.observe.spi.service.ServiceContext; +import fr.ird.observe.spi.validation.callback.EntityInterceptorCallback; + +import java.util.Deque; + +/** + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.3.4 + */ +@SuppressWarnings("rawtypes") +@AutoService(EntityInterceptorCallback.class) +public class SetInterceptorCallback implements EntityInterceptorCallback<SetDto, Set, SetSpi> { + + + @Override + public boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType) { + return Set.class.equals(entityType); + } + + @Override + public void loadDtoForValidation(ServiceContext context, Deque<Entity> path, SetSpi spi, Set set, SetDto dto) { + Trip trip = (Trip) path.getFirst(); + Activity activity = EntityInterceptorCallback.getParent(path, set, Activity.class); + spi.loadDtoForValidation(context, trip, activity, dto); + } +} ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ll/observation/SetSpi.java ===================================== @@ -109,20 +109,28 @@ public class SetSpi extends GeneratedSetSpi { // on reporte la position de l'activité pour la position de début de filage preCreated.setSettingStartLatitude(parent.getLatitude()); preCreated.setSettingStartLongitude(parent.getLongitude()); - Form<SetDto> form = super.preCreate(context, parent, preCreated); - form.getObject().setOtherSets(getBrothers(context, parent)); - return form; + //FIXME super.preCreate does already this? +// Form<SetDto> form = super.preCreate(context, parent, preCreated); +// form.getObject().setOtherSets(getBrothers(context, parent)); + return super.preCreate(context, parent, preCreated); } @Override - public void loadDtoForValidation(ServiceContext context, Activity parent, Set entity, SetDto dto) { - super.loadDtoForValidation(context, parent, entity, dto); + public void loadDtoForValidation(ServiceContext context, Activity parent, Set entity, SetDto dto) { dto.setOtherSets(getBrothers(context, parent)); } + public void loadDtoForValidation(ServiceContext context, Trip trip, Activity parent, SetDto dto) { + dto.setOtherSets(getBrothers(context, trip, parent)); + } + public java.util.Set<SetStubDto> getBrothers(ServiceContext context, Activity parent) { - java.util.Set<SetStubDto> result = new HashSet<>(); Trip trip = Activity.SPI.getParent(context, parent.getTopiaId()); + return getBrothers(context, trip, parent); + } + + public java.util.Set<SetStubDto> getBrothers(ServiceContext context, Trip trip, Activity parent) { + java.util.Set<SetStubDto> result = new HashSet<>(); ReferentialLocale referentialLocale = context.getReferentialLocale(); trip.getActivityObs().stream().filter(a -> a.getVesselActivity().isAllowSet()).filter(a -> !Objects.equals(a, parent) && a.getSet() != null).forEach( oneParent -> { ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/common/TripBatchSpi.java ===================================== @@ -38,7 +38,6 @@ public class TripBatchSpi extends GeneratedTripBatchSpi { @Override public void loadDtoForValidation(ServiceContext context, Trip entity, TripBatchDto dto) { - super.loadDtoForValidation(context, entity, dto); LinkedHashSet<String> availablePackagingIds = getAvailablePackagingIds(context, entity); dto.setAvailablePackagingIds(availablePackagingIds); LinkedHashSet<String> availableBuyerIds = getAvailableBuyerIds(context, entity); ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/common/TripSpi.java ===================================== @@ -143,7 +143,6 @@ public class TripSpi extends GeneratedTripSpi { @Override public void loadDtoForValidation(ServiceContext context, Trip entity, TripDto dto) { - super.loadDtoForValidation(context, entity, dto); entity.buildStatistics(dto); } ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/localmarket/SurveySpi.java ===================================== @@ -47,15 +47,16 @@ public class SurveySpi extends GeneratedSurveySpi { @Override public Form<SurveyDto> preCreate(ServiceContext context, Trip parent, Survey preCreated) { - Form<SurveyDto> form = super.preCreate(context, parent, preCreated); - form.getObject().setNumber(parent.getLocalmarketSurveySize() + 1); - fillFormObject(context.getReferentialLocale(), parent, preCreated, form.getObject()); - return form; + preCreated.setNumber(parent.getLocalmarketSurveySize() + 1); +// Form<SurveyDto> form = super.preCreate(context, parent, preCreated); +// form.getObject().setNumber(parent.getLocalmarketSurveySize() + 1); + //FIXME super.preCreate does already this? +// fillFormObject(context.getReferentialLocale(), parent, preCreated, form.getObject()); + return super.preCreate(context, parent, preCreated); } @Override public void loadDtoForValidation(ServiceContext context, Trip parent, Survey entity, SurveyDto dto) { - super.loadDtoForValidation(context, parent, entity, dto); fillFormObject(context.getReferentialLocale(), parent, entity, dto); } ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/logbook/ActivitySpi.java ===================================== @@ -105,9 +105,10 @@ public class ActivitySpi extends GeneratedActivitySpi { preCreated.setNumber(number); preCreated.setSetCount(1); preCreated.setInformationSource(InformationSource.loadEntity(context, ProtectedIdsPs.PS_LOGBOOK_ACTIVITY_DEFAULT_INFORMATION_SOURCE_ID)); - Form<ActivityDto> form = super.preCreate(context, parent, preCreated); - addRouteDate(parent, form.getObject()); - return form; + //FIXME super.preCreate does already this? +// Form<ActivityDto> form = super.preCreate(context, parent, preCreated); +// addRouteDate(parent, form.getObject()); + return super.preCreate(context, parent, preCreated); } @Override ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/logbook/SampleInterceptorCallback.java ===================================== @@ -0,0 +1,55 @@ +package fr.ird.observe.entities.data.ps.logbook; + +/*- + * #%L + * ObServe Core :: Persistence :: Java + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.auto.service.AutoService; +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.dto.data.ps.logbook.SampleDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.entities.data.ps.common.Trip; +import fr.ird.observe.spi.service.ServiceContext; +import fr.ird.observe.spi.validation.callback.EntityInterceptorCallback; + +import java.util.Deque; + +/** + * Created at 22/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.3.4 + */ +@SuppressWarnings("rawtypes") +@AutoService(EntityInterceptorCallback.class) +public class SampleInterceptorCallback implements EntityInterceptorCallback<SampleDto, Sample, SampleSpi> { + + @Override + public boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType) { + return Sample.class.equals(entityType); + } + + @Override + public void loadDtoForValidation(ServiceContext context, Deque<Entity> path, SampleSpi spi, Sample sample, SampleDto dto) { + Trip trip = EntityInterceptorCallback.getParent(path, sample, Trip.class); + spi.loadDtoForValidation(context, trip, dto); + } +} ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/logbook/SampleSpi.java ===================================== @@ -23,6 +23,7 @@ package fr.ird.observe.entities.data.ps.logbook; */ import fr.ird.observe.dto.ProtectedIdsPs; +import fr.ird.observe.dto.data.ps.logbook.ActivityStubDto; import fr.ird.observe.dto.data.ps.logbook.SampleDto; import fr.ird.observe.dto.form.Form; import fr.ird.observe.dto.referential.ReferentialLocale; @@ -33,6 +34,8 @@ import fr.ird.observe.services.service.SaveResultDto; import fr.ird.observe.spi.result.AddEntityToUpdateStep; import fr.ird.observe.spi.service.ServiceContext; +import java.util.LinkedList; +import java.util.List; import java.util.Objects; import java.util.function.Consumer; @@ -45,7 +48,6 @@ import java.util.function.Consumer; public class SampleSpi extends GeneratedSampleSpi { @Override public void loadDtoForValidation(ServiceContext context, Trip parent, Sample entity, SampleDto dto) { - super.loadDtoForValidation(context, parent, entity, dto); dto.setActivity(Trip.SPI.getLogbookSetActivities(context, parent.getId())); } @@ -64,9 +66,10 @@ public class SampleSpi extends GeneratedSampleSpi { preCreated.setSampleType(SampleType.loadEntity(context, ProtectedIdsPs.PS_LOGBOOK_SAMPLE_DEFAULT_SAMPLE_TYPE_ID)); preCreated.setSampleQuality(SampleQuality.loadEntity(context, ProtectedIdsPs.PS_LOGBOOK_SAMPLE_DEFAULT_SAMPLE_QUALITY_ID)); preCreated.setSuperSample(false); - Form<SampleDto> form = super.preCreate(context, parent, preCreated); - form.getObject().setActivity(Trip.SPI.getLogbookSetActivities(context, parent.getTopiaId())); - return form; + //FIXME super.preCreate does already this? +// Form<SampleDto> form = super.preCreate(context, parent, preCreated); +// form.getObject().setActivity(Trip.SPI.getLogbookSetActivities(context, parent.getTopiaId())); + return super.preCreate(context, parent, preCreated); } @Override @@ -90,6 +93,15 @@ public class SampleSpi extends GeneratedSampleSpi { return super.onSave(context, parent, entity, dto, needCopy); } + public void loadDtoForValidation(ServiceContext context, Trip parent, SampleDto dto) { + List<ActivityStubDto> logbookSetActivities = new LinkedList<>(); + for (Route route : parent.getRouteLogbook()) { + List<ActivityStubDto> routeActivities = Activity.ACTIVITY_STUB_SPI.toDataDtoList(context.getReferentialLocale(), route.getActivity()); + logbookSetActivities.addAll(routeActivities); + } + dto.setActivity(logbookSetActivities); + } + private int getSampleSpeciesSubNumber(Sample entity) { return (int) entity.getSampleSpecies().stream().mapToInt(SampleSpecies::getSubSampleNumber).distinct().count(); } ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/RouteSpi.java ===================================== @@ -76,7 +76,6 @@ public class RouteSpi extends GeneratedRouteSpi { @Override public void loadDtoForValidation(ServiceContext context, Trip parent, Route entity, RouteDto dto) { - super.loadDtoForValidation(context, parent, entity, dto); bindEndOfSearchingProperties(entity.getActivity(), dto.getActivity()); } ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/SampleSpi.java ===================================== @@ -48,7 +48,6 @@ public class SampleSpi extends GeneratedSampleSpi { @Override public void loadDtoForValidation(ServiceContext context, Set parent, Sample entity, SampleDto dto) { - super.loadDtoForValidation(context, entity, dto); dto.setId(parent.getTopiaId()); dto.setSpeciesFateBySpeciesMap(getCatchesSpeciesFateBySpeciesId(parent)); } ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/SetInterceptorCallback.java ===================================== @@ -0,0 +1,55 @@ +package fr.ird.observe.entities.data.ps.observation; + +/*- + * #%L + * ObServe Core :: Persistence :: Java + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.auto.service.AutoService; +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.dto.data.ps.observation.SetDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.spi.service.ServiceContext; +import fr.ird.observe.spi.validation.callback.EntityInterceptorCallback; + +import java.util.Deque; + +/** + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.3.4 + */ +@SuppressWarnings("rawtypes") +@AutoService(EntityInterceptorCallback.class) +public class SetInterceptorCallback implements EntityInterceptorCallback<SetDto, Set, SetSpi> { + + @Override + public boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType) { + return Set.class.equals(entityType); + } + + @Override + public void loadDtoForValidation(ServiceContext context, Deque<Entity> path, SetSpi spi, Set set, SetDto dto) { + Activity activity = EntityInterceptorCallback.getParent(path, set, Activity.class); + Route route = EntityInterceptorCallback.getParent(path, activity, Route.class); + spi.loadDtoForValidation(route, dto); + } +} ===================================== core/persistence/java/src/main/java/fr/ird/observe/entities/data/ps/observation/SetSpi.java ===================================== @@ -62,19 +62,24 @@ public class SetSpi extends GeneratedSetSpi { // See https://gitlab.com/ultreiaio/ird-observe/-/issues/2573 SchoolType schoolType = SchoolType.loadEntity(context, ProtectedIdsPs.PS_COMMON_SCHOOL_TYPE_UNDEFINED_ID); preCreated.setSchoolType(schoolType); - Form<SetDto> form = super.preCreate(context, parent, preCreated); - form.getObject().setStartSetDate(routeDate); - return form; + //FIXME super.preCreate does already this? +// Form<SetDto> form = super.preCreate(context, parent, preCreated); +// form.getObject().setStartSetDate(routeDate); + return super.preCreate(context, parent, preCreated); } @Override public void loadDtoForValidation(ServiceContext context, Activity parent, Set entity, SetDto dto) { - super.loadDtoForValidation(context, parent, entity, dto); Route route = Activity.SPI.getParent(context, parent.getTopiaId()); Date routeDate = route.getDate(); dto.setStartSetDate(routeDate); } + public void loadDtoForValidation(Route route, SetDto dto) { + Date routeDate = route.getDate(); + dto.setStartSetDate(routeDate); + } + @Override public void onSave(ServiceContext context, Activity parent, Set entity, SetDto dto) { entity.setActivity(parent); ===================================== core/services/local/src/test/java/fr/ird/observe/services/local/service/api/DataEntityServiceLocalWriteTest.java ===================================== @@ -34,7 +34,6 @@ import fr.ird.observe.test.DatabaseName; import fr.ird.observe.test.spi.CopyDatabaseConfiguration; import fr.ird.observe.test.spi.DatabaseNameConfiguration; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import java.util.Collection; @@ -70,7 +69,6 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL } @Test - @Ignore @CopyDatabaseConfiguration @DatabaseNameConfiguration(DatabaseName.referential) public void createPsTrip() throws InvalidDataException { @@ -113,7 +111,6 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL @Test - @Ignore @CopyDatabaseConfiguration public void createPsTrip2() throws InvalidDataException { DataSourceValidationMode validationMode = TOPIA_TEST_CLASS_RESOURCE.getServiceInitializerConfig().getValidationMode(); @@ -270,7 +267,6 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL } @Test - @Ignore @CopyDatabaseConfiguration public void createLlTrip() throws InvalidDataException { TOPIA_TEST_CLASS_RESOURCE.getServiceInitializerConfig().setValidationMode(DataSourceValidationMode.NONE); @@ -296,6 +292,16 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL } } + @Test + @CopyDatabaseConfiguration + public void createLlTrip_2886() throws InvalidDataException { + TOPIA_TEST_CLASS_RESOURCE.getServiceInitializerConfig().setValidationMode(DataSourceValidationMode.STRONG); + { + Map<String, Object> data = assertCreateTrip0(fr.ird.observe.services.service.data.ll.common.TripService.class, + fr.ird.observe.dto.data.ll.common.TripDto.class, "issue2886"); + Assert.assertNotNull(data); + } + } @Test @CopyDatabaseConfiguration @@ -308,7 +314,6 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL } } - @Test @CopyDatabaseConfiguration public void createLlTripActivityObs() throws InvalidDataException { @@ -320,7 +325,6 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL } } - @Test @CopyDatabaseConfiguration public void createLlTripActivityLogbook() throws InvalidDataException { @@ -332,7 +336,6 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL } } - @Test @CopyDatabaseConfiguration public void createLlTripAll() throws InvalidDataException { @@ -372,7 +375,6 @@ public class DataEntityServiceLocalWriteTest extends GeneratedDataEntityServiceL return data; } - protected Map<String, Object> assertCreateTrip0(Class<?> serviceType, Class<? extends DataDto> dtoType, String classifier) throws InvalidDataException { String json = fixtures.loadContent(serviceType, classifier); ToolkitTreeNodeStates result = fixtures.testCreate(service, dtoType, json); ===================================== core/services/test/src/main/resources/fixtures/fr/ird/observe/services/service/data/ll/common/TripService-issue2886.json ===================================== @@ -0,0 +1,1828 @@ +{ + "homeId": null, + "startDate": "2023-03-08T00:00:00.000Z", + "endDate": "2023-03-30T00:00:00.000Z", + "noOfCrewMembers": "27", + "ersId": null, + "gearUseFeatures": null, + "activityObs": null, + "activityLogbook": [ + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-08T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -20.15, + "longitude": 57.483333333333334, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-09T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -21.883333333333333, + "longitude": 55.63333333333333, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-10T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -24.116666666666667, + "longitude": 52.63333333333333, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-11T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -24.05, + "longitude": 52.333333333333336, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-12T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -21.5, + "longitude": 53.333333333333336, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-13T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -17.0, + "longitude": 52.28333333333333, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-14T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -13.366666666666667, + "longitude": 53.3, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-15T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -10.1, + "longitude": 52.5, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-16T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -7.016666666666667, + "longitude": 50.86666666666667, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-17T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -4.733333333333333, + "longitude": 48.166666666666664, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-18T05:00:00.000Z", + "endTimeStamp": null, + "latitude": -3.5, + "longitude": 46.86666666666667, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 175.0, + "totalHooksCount": 3500, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-18T05:00:00.000Z", + "settingStartLatitude": -3.5, + "settingStartLongitude": 46.86666666666667, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 1.0, + "totalWeight": 14.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 15.0, + "totalWeight": 310.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 2.0, + "totalWeight": 34.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683791#0.20975568563021063", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 6.0, + "totalWeight": 191.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 1.0, + "totalWeight": 96.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683731#0.3892121873590658", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-19T10:00:00.000Z", + "endTimeStamp": null, + "latitude": -3.3833333333333333, + "longitude": 46.7, + "seaSurfaceTemperature": 31, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 150.0, + "totalHooksCount": 3000, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-19T10:00:00.000Z", + "settingStartLatitude": -3.3833333333333333, + "settingStartLongitude": 46.7, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 3.0, + "totalWeight": 262.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 11.0, + "totalWeight": 221.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 3.0, + "totalWeight": 70.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 1.0, + "totalWeight": 39.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683731#0.3892121873590658", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-20T09:00:00.000Z", + "endTimeStamp": null, + "latitude": -3.3, + "longitude": 47.083333333333336, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 150.0, + "totalHooksCount": 3000, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-20T09:00:00.000Z", + "settingStartLatitude": -3.3, + "settingStartLongitude": 47.083333333333336, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 5.0, + "totalWeight": 321.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 12.0, + "totalWeight": 210.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 2.0, + "totalWeight": 55.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 1.0, + "totalWeight": 105.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683731#0.3892121873590658", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-21T08:00:00.000Z", + "endTimeStamp": null, + "latitude": -3.466666666666667, + "longitude": 47.0, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 150.0, + "totalHooksCount": 3000, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-21T08:00:00.000Z", + "settingStartLatitude": -3.466666666666667, + "settingStartLongitude": 47.0, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-22T09:00:00.000Z", + "endTimeStamp": null, + "latitude": -3.3833333333333333, + "longitude": 47.28333333333333, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 150.0, + "totalHooksCount": 3000, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-22T09:00:00.000Z", + "settingStartLatitude": -3.3833333333333333, + "settingStartLongitude": 47.28333333333333, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 2.0, + "totalWeight": 114.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 5.0, + "totalWeight": 93.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 2.0, + "totalWeight": 51.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 1.0, + "totalWeight": 70.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683731#0.3892121873590658", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-23T00:00:00.000Z", + "endTimeStamp": null, + "latitude": -1.95, + "longitude": 47.916666666666664, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-24T03:00:00.000Z", + "endTimeStamp": null, + "latitude": -0.65, + "longitude": 48.45, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 175.0, + "totalHooksCount": 3500, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-24T03:00:00.000Z", + "settingStartLatitude": -0.65, + "settingStartLongitude": 48.45, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 7.0, + "totalWeight": 181.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 8.0, + "totalWeight": 224.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 4.0, + "totalWeight": 95.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683791#0.20975568563021063", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 2.0, + "totalWeight": 51.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": "Other fish non specified", + "count": 5.0, + "totalWeight": 28.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1433499266610#0.696541526820511", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.1", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-25T04:00:00.000Z", + "endTimeStamp": null, + "latitude": -0.9166666666666666, + "longitude": 47.983333333333334, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 175.0, + "totalHooksCount": 3500, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-25T04:00:00.000Z", + "settingStartLatitude": -0.9166666666666666, + "settingStartLongitude": 47.983333333333334, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 6.0, + "totalWeight": 375.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 11.0, + "totalWeight": 309.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 3.0, + "totalWeight": 98.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-26T05:00:00.000Z", + "endTimeStamp": null, + "latitude": -1.0833333333333333, + "longitude": 47.63333333333333, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 175.0, + "totalHooksCount": 3500, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-26T05:00:00.000Z", + "settingStartLatitude": -1.0833333333333333, + "settingStartLongitude": 47.63333333333333, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 4.0, + "totalWeight": 268.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 4.0, + "totalWeight": 84.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 3.0, + "totalWeight": 78.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-27T11:30:00.000Z", + "endTimeStamp": null, + "latitude": -0.6333333333333333, + "longitude": 48.03333333333333, + "seaSurfaceTemperature": 30, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#1239832686138#0.1", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": { + "homeId": null, + "comment": null, + "number": null, + "basketsPerSectionCount": null, + "branchlinesPerBasketCount": null, + "totalSectionsCount": null, + "totalBasketsCount": 125.0, + "totalHooksCount": 2500, + "totalLightsticksCount": null, + "weightedSnap": false, + "snapWeight": null, + "weightedSwivel": false, + "swivelWeight": null, + "timeBetweenHooks": null, + "shooterUsed": false, + "shooterSpeed": null, + "maxDepthTargeted": null, + "settingStartTimeStamp": "2023-03-27T11:30:00.000Z", + "settingStartLatitude": -0.6333333333333333, + "settingStartLongitude": 48.03333333333333, + "settingEndTimeStamp": null, + "settingEndLatitude": null, + "settingEndLongitude": null, + "settingVesselSpeed": null, + "haulingDirectionSameAsSetting": null, + "haulingStartTimeStamp": null, + "haulingStartLatitude": null, + "haulingStartLongitude": null, + "haulingEndTimeStamp": null, + "haulingEndLatitude": null, + "haulingEndLongitude": null, + "haulingBreaks": null, + "monitored": false, + "totalLineLength": null, + "basketLineLength": null, + "lengthBetweenBranchlines": 37, + "baitsComposition": [ + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1433499458077#0.820353789720684" + }, + { + "homeId": null, + "proportion": 50.0, + "individualSize": null, + "individualWeight": null, + "baitSettingStatus": null, + "baitType": "fr.ird.referential.ll.common.BaitType#1239832686124#1.0" + } + ], + "floatlinesComposition": [ + { + "homeId": null, + "length": 30, + "proportion": 100, + "lineType": "fr.ird.referential.ll.common.LineType#1239832686157#0.9" + } + ], + "hooksComposition": [], + "settingShape": null, + "catches": [ + { + "homeId": null, + "comment": null, + "count": 1.0, + "totalWeight": 73.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 4.0, + "totalWeight": 73.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.4", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 2.0, + "totalWeight": 54.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683791#0.20975568563021063", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + }, + { + "homeId": null, + "comment": null, + "count": 3.0, + "totalWeight": 88.0, + "hookWhenDiscarded": null, + "depredated": null, + "beatDiameter": null, + "photoReferences": null, + "number": null, + "acquisitionMode": null, + "countDepredated": null, + "depredatedProportion": null, + "tagNumber": null, + "catchFate": "fr.ird.referential.ll.common.CatchFate#1239832686125#0.2", + "discardHealthStatus": null, + "species": "fr.ird.referential.common.Species#1239832683785#0.49501050869628815", + "predator": [], + "catchHealthStatus": null, + "onBoardProcessing": "fr.ird.referential.ll.common.OnBoardProcessing#1464000000000#0.3", + "weightMeasureMethod": null + } + ], + "lineType": null, + "lightsticksUsed": false, + "lightsticksType": null, + "lightsticksColor": null, + "mitigationType": [], + "branchlinesComposition": [] + } + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-28T00:00:00.000Z", + "endTimeStamp": null, + "latitude": 0.18333333333333332, + "longitude": 49.733333333333334, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-29T00:00:00.000Z", + "endTimeStamp": null, + "latitude": 1.6333333333333333, + "longitude": 52.416666666666664, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + }, + { + "homeId": null, + "comment": null, + "startTimeStamp": "2023-03-30T00:00:00.000Z", + "endTimeStamp": null, + "latitude": 3.4166666666666665, + "longitude": 55.4, + "seaSurfaceTemperature": null, + "wind": null, + "windDirection": null, + "currentSpeed": null, + "currentDirection": null, + "vesselActivity": "fr.ird.referential.ll.common.VesselActivity#666#01", + "dataQuality": null, + "fpaZone": null, + "relatedObservedActivity": null, + "set": null, + "sample": null + } + ], + "landing": null, + "sample": null, + "tripType": "fr.ird.referential.ll.common.TripType#1464000000000#02", + "observationMethod": null, + "observer": "fr.ird.referential.common.Person#1254317601353#0.6617065204572095", + "vessel": "fr.ird.referential.common.Vessel#1239832677756#0.4935293150142165", + "observationsProgram": null, + "logbookProgram": "fr.ird.referential.ll.common.Program#1239832686139#0.1", + "captain": "fr.ird.referential.common.Person#1254317601353#0.6617065204572095", + "observationsDataEntryOperator": null, + "logbookDataEntryOperator": "fr.ird.referential.common.Person#1254317601353#0.6617065204572095", + "sampleDataEntryOperator": null, + "landingDataEntryOperator": null, + "ocean": "fr.ird.referential.common.Ocean#1239832686152#0.8325731048817705", + "departureHarbour": "fr.ird.referential.common.Harbour#11#0.42", + "landingHarbour": null, + "observationsDataQuality": null, + "logbookDataQuality": null, + "generalComment": null, + "observationsComment": null, + "logbookComment": null, + "species": [ + "fr.ird.referential.common.Species#1239832685474#0.8943253454598569", + "fr.ird.referential.common.Species#1239832685475#0.13349466123905152", + "fr.ird.referential.common.Species#1239832685476#0.5618871286604711", + "fr.ird.referential.common.Species#1239832683791#0.20975568563021063" + ], + "observationsAvailability": false, + "logbookAvailability": true +} \ No newline at end of file ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/context/EditableDtoEntityContext.java ===================================== @@ -102,11 +102,10 @@ public abstract class EditableDtoEntityContext< } public void loadDtoForValidation(ServiceContext context, PE parent, E entity, D dto) { - super.loadDtoForValidation(context, entity, dto); } @Override - public void loadDtoForValidation(ServiceContext context, E entity, D dto) { + public final void loadDtoForValidation(ServiceContext context, E entity, D dto) { PE parent = getParent(context, entity.getTopiaId()); loadDtoForValidation(context, parent, entity, dto); } ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/context/OpenableDtoEntityContext.java ===================================== @@ -181,12 +181,12 @@ public abstract class OpenableDtoEntityContext< ToolkitParentIdDtoBean parentId = getParentId(context, id); return parentSpi().loadEntity(context, parentId.getTopiaId()); } + public void loadDtoForValidation(ServiceContext context, PE parent, E entity, D dto) { - super.loadDtoForValidation(context, entity, dto); } @Override - public void loadDtoForValidation(ServiceContext context, E entity, D dto) { + public final void loadDtoForValidation(ServiceContext context, E entity, D dto) { PE parent = getParent(context, entity.getTopiaId()); loadDtoForValidation(context, parent, entity, dto); } ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/EntityInterceptor.java ===================================== @@ -23,15 +23,11 @@ package fr.ird.observe.spi.validation; */ import fr.ird.observe.dto.BusinessDto; -import fr.ird.observe.dto.data.EditableDto; -import fr.ird.observe.dto.data.OpenableDto; import fr.ird.observe.dto.referential.ReferentialLocale; import fr.ird.observe.entities.Entity; -import fr.ird.observe.entities.data.DataEntity; import fr.ird.observe.spi.context.DtoEntityContext; -import fr.ird.observe.spi.context.EditableDtoEntityContext; -import fr.ird.observe.spi.context.OpenableDtoEntityContext; import fr.ird.observe.spi.service.ServiceContext; +import fr.ird.observe.spi.validation.callback.EntityInterceptorCallback; import fr.ird.observe.validation.ValidationContextSupport; import fr.ird.observe.validation.api.result.ValidationResultDtoMessage; import io.ultreia.java4all.decoration.Decorator; @@ -40,7 +36,6 @@ import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; import java.util.Deque; import java.util.LinkedList; -import java.util.List; import java.util.Objects; import java.util.TreeMap; import java.util.function.Consumer; @@ -50,24 +45,27 @@ import java.util.function.Consumer; * * @author Tony Chemit - dev@tchemit.fr */ -public class EntityInterceptor<D extends BusinessDto, E extends Entity> { - private final DtoEntityContext<D, ?, E, ?> spi; +public class EntityInterceptor<D extends BusinessDto, E extends Entity, S extends DtoEntityContext<D, ?, E, ?>> { + private final S spi; private final Consumer<String> dataContextConsumer; private final SimpleBeanValidator<D> validator; private final TreeMap<String, D> cache; private final ReferentialLocale referentialLocale; private final Decorator decorator; + private final EntityInterceptorCallback<D, E, S> callback; - EntityInterceptor(DtoEntityContext<D, ?, E, ?> spi, + EntityInterceptor(S spi, Consumer<String> dataContextConsumer, SimpleBeanValidator<D> validator, ReferentialLocale referentialLocale, - Decorator decorator) { + Decorator decorator, + EntityInterceptorCallback<D, E, S> callback) { this.spi = spi; this.dataContextConsumer = dataContextConsumer; this.validator = validator; this.referentialLocale = referentialLocale; this.decorator = decorator; + this.callback = Objects.requireNonNull(callback); this.cache = new TreeMap<>(); } @@ -77,17 +75,7 @@ public class EntityInterceptor<D extends BusinessDto, E extends Entity> { if (validator != null) { D dto = cache.computeIfAbsent(e.getTopiaId(), id -> { D result = spi.toDto(referentialLocale, e); - if (result instanceof EditableDto) { - @SuppressWarnings("rawtypes") EditableDtoEntityContext spi1 = (EditableDtoEntityContext) spi; - Entity parent = getParent(path, e, spi1.parentSpi().toEntityType()); - spi1.loadDtoForValidation(context, parent, (DataEntity) e, (EditableDto) result); - } else if (result instanceof OpenableDto) { - @SuppressWarnings("rawtypes") OpenableDtoEntityContext spi1 = (OpenableDtoEntityContext) spi; - Entity parent = getParent(path, e, spi1.parentSpi().toEntityType()); - spi1.loadDtoForValidation(context, parent, (DataEntity) e, (OpenableDto) result); - } else { - spi.loadDtoForValidation(context, e, result); - } + callback.loadDtoForValidation(context, path, spi, e, result); return result; }); if (dataContextConsumer != null) { @@ -99,16 +87,6 @@ public class EntityInterceptor<D extends BusinessDto, E extends Entity> { return null; } - private Entity getParent(Deque<Entity> path, E e, Class<? extends DataEntity> parentType) { - List<Entity> copy = List.copyOf(path); - int parentPosition = copy.indexOf(e) - 1; - Entity parent = copy.get(parentPosition); - while (!parentType.isAssignableFrom(parent.getClass())) { - parent = copy.get(--parentPosition); - } - return Objects.requireNonNull(parent); - } - void release(ValidationContextSupport validationContext, String id) { if (dataContextConsumer != null) { dataContextConsumer.accept(null); ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/EntityInterceptors.java ===================================== @@ -27,13 +27,16 @@ import fr.ird.observe.dto.data.DataDto; import fr.ird.observe.dto.data.NotEntityDto; import fr.ird.observe.dto.referential.ReferentialDto; import fr.ird.observe.dto.referential.ReferentialLocale; -import fr.ird.observe.entities.Entity; +import fr.ird.observe.entities.data.DataEntity; +import fr.ird.observe.entities.referential.ReferentialEntity; import fr.ird.observe.navigation.id.IdModel; import fr.ird.observe.navigation.id.IdNode; import fr.ird.observe.navigation.id.IdProject; import fr.ird.observe.spi.PersistenceBusinessProject; import fr.ird.observe.spi.context.DataDtoEntityContext; import fr.ird.observe.spi.context.ReferentialDtoEntityContext; +import fr.ird.observe.spi.validation.callback.EntityInterceptorCallback; +import fr.ird.observe.spi.validation.callback.EntityInterceptorCallbacks; import fr.ird.observe.validation.ValidationContextSupport; import fr.ird.observe.validation.ValidatorsMap; import io.ultreia.java4all.decoration.Decorator; @@ -57,10 +60,12 @@ import java.util.Set; public class EntityInterceptors { private static final Logger log = LogManager.getLogger(EntityInterceptors.class); - public static Map<Class<?>, EntityInterceptor<?, ?>> forReferential(ValidatorsMap validators, - ValidationContextSupport validationDataContext, - ReferentialLocale referentialLocale) { - Map<Class<?>, EntityInterceptor<?, ?>> result = new LinkedHashMap<>(); + private static final EntityInterceptorCallbacks CALLBACKS = new EntityInterceptorCallbacks(); + + public static Map<Class<?>, EntityInterceptor<?, ?, ?>> forReferential(ValidatorsMap validators, + ValidationContextSupport validationDataContext, + ReferentialLocale referentialLocale) { + Map<Class<?>, EntityInterceptor<?, ?, ?>> result = new LinkedHashMap<>(); Set<Class<?>> possibleTypes = new LinkedHashSet<>(validators.keySet()); possibleTypes.removeIf(t -> NotEntityDto.class.isAssignableFrom(t) || DataDto.class.isAssignableFrom(t)); DecoratorService decoratorService = validationDataContext.getDecoratorService(); @@ -70,12 +75,12 @@ public class EntityInterceptors { return result; } - public static Map<Class<?>, EntityInterceptor<?, ?>> forData(ValidatorsMap validators, - ValidationContextSupport validationDataContext, - IdProject dataContext, - ReferentialLocale referentialLocale) { + public static Map<Class<?>, EntityInterceptor<?, ?, ?>> forData(ValidatorsMap validators, + ValidationContextSupport validationDataContext, + IdProject dataContext, + ReferentialLocale referentialLocale) { - Map<Class<?>, EntityInterceptor<?, ?>> result = new LinkedHashMap<>(); + Map<Class<?>, EntityInterceptor<?, ?, ?>> result = new LinkedHashMap<>(); Set<Class<?>> possibleTypes = new LinkedHashSet<>(validators.keySet()); possibleTypes.removeIf(t -> NotEntityDto.class.isAssignableFrom(t) || ReferentialDto.class.isAssignableFrom(t)); @@ -114,43 +119,45 @@ public class EntityInterceptors { } static <D extends ReferentialDto> void toReferential(Class<D> dtoType, - Map<Class<?>, EntityInterceptor<?, ?>> interceptorsBuilder, + Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptorsBuilder, ValidatorsMap validators, ReferentialLocale referentialLocale, DecoratorService decoratorService) { SimpleBeanValidator<D> validator = validators.getValidator(dtoType); - ReferentialDtoEntityContext<D, ?, ?, ?> spi = PersistenceBusinessProject.fromReferentialDto(dtoType); - Class<? extends Entity> entityType = spi.toEntityType(); + ReferentialDtoEntityContext<D, ?, ReferentialEntity, ?> spi = PersistenceBusinessProject.fromReferentialDto(dtoType); + Class<ReferentialEntity> entityType = spi.toEntityType(); Decorator decorator = decoratorService.getDecoratorByType(entityType); - EntityInterceptor<D, ?> interceptor = new EntityInterceptor<>(spi, null, validator, referentialLocale, decorator); + EntityInterceptorCallback<D, ReferentialEntity, ReferentialDtoEntityContext<D, ?, ReferentialEntity, ?>> callback = CALLBACKS.getCallback(dtoType, entityType); + EntityInterceptor<D, ?, ?> interceptor = new EntityInterceptor<>(spi, null, validator, referentialLocale, decorator, callback); interceptorsBuilder.put(entityType, interceptor); } - static <D extends DataDto> void toData(Class<D> dtoType, - IdNode<D> consumer, - Map<Class<?>, EntityInterceptor<?, ?>> interceptorsBuilder, - ValidatorsMap validators, - ReferentialLocale referentialLocale, - DecoratorService decoratorService) { + static <D extends DataDto, E extends DataEntity> void toData(Class<D> dtoType, + IdNode<D> consumer, + Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptorsBuilder, + ValidatorsMap validators, + ReferentialLocale referentialLocale, + DecoratorService decoratorService) { SimpleBeanValidator<D> validator = validators.getValidator(dtoType); if (validator == null) { log.warn(String.format("Not a main type (%s), skip it", dtoType)); return; } - DataDtoEntityContext<D, ?, ?, ?> spi = PersistenceBusinessProject.fromDataDto(dtoType); - Class<?> entityType = spi.toEntityType(); + DataDtoEntityContext<D, ?, E, ?> spi = PersistenceBusinessProject.fromDataDto(dtoType); + Class<E> entityType = spi.toEntityType(); Objects.requireNonNull(entityType); if (interceptorsBuilder.containsKey(entityType)) { return; } Decorator decorator = decoratorService.getDecoratorByType(entityType); - EntityInterceptor<D, ?> interceptor = new EntityInterceptor<>(spi, consumer == null ? null : consumer::setId, validator, referentialLocale, decorator); + EntityInterceptorCallback<D, E, DataDtoEntityContext<D, ?, E, ?>> callback = CALLBACKS.getCallback(dtoType, entityType); + EntityInterceptor<D, E, DataDtoEntityContext<D, ?, E, ?>> interceptor = new EntityInterceptor<>(spi, consumer == null ? null : consumer::setId, validator, referentialLocale, decorator, callback); interceptorsBuilder.put(entityType, interceptor); } static <D extends DataDto> void toData(IdNode<D> consumer, - Map<Class<?>, EntityInterceptor<?, ?>> interceptorsBuilder, + Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptorsBuilder, ValidatorsMap validators, ReferentialLocale referentialLocale, DecoratorService decoratorService) { ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/ValidationMessageDetector.java ===================================== @@ -58,11 +58,74 @@ public class ValidationMessageDetector { private final ValidationEntityVisitor entityVisitor; + private ValidationMessageDetector(ServiceContext context, + ReferentialLocale referentialLocale, + ValidationContextSupport validationDataContext, + ValidationResultBuilder resultBuilder, + Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptors, + boolean canWalkInSubclasses) { + this.entityVisitor = new ValidationEntityVisitor(context, + validationDataContext, + interceptors, + resultBuilder, + new MessagesCollector(referentialLocale.getLocale()), + canWalkInSubclasses); + } + + public static ValidationMessageDetector forData(ServiceContext context, + ValidatorsMap validators, + ValidationContextSupport validationDataContext, + IdProject selectModel, + ReferentialLocale referentialLocale, + ValidationResultBuilder resultBuilder) { + Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptors = EntityInterceptors.forData(validators, + validationDataContext, + selectModel, + referentialLocale); + return new ValidationMessageDetector(context, + referentialLocale, + validationDataContext, + resultBuilder, + interceptors, + true); + } + + public static ValidationMessageDetector forReferential(ServiceContext context, + ValidatorsMap validators, + ValidationContextSupport validationDataContext, + ReferentialLocale referentialLocale, + ValidationResultBuilder resultBuilder) { + Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptors = EntityInterceptors.forReferential(validators, + validationDataContext, + referentialLocale); + return new ValidationMessageDetector(context, + referentialLocale, + validationDataContext, + resultBuilder, + interceptors, + false); + } + + public <E extends Entity> void detectValidationMessages(E entity) { + try { + entity.accept(entityVisitor); + } finally { + entityVisitor.clear(); + } + } + + public <E extends Entity> void detectValidationMessages(Iterable<E> entities) { + for (E entity : entities) { + entity.accept(entityVisitor); + } + entityVisitor.clear(); + } + private static class ValidationEntityVisitor implements TopiaEntityVisitor { private final ServiceContext context; private final ValidationContextSupport validationDataContext; - private final Map<Class<?>, EntityInterceptor<?, ?>> interceptors; + private final Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptors; private final Deque<Entity> path; private final Set<TopiaEntity> explored; private final ValidationResultBuilder resultBuilder; @@ -72,7 +135,7 @@ public class ValidationMessageDetector { ValidationEntityVisitor(ServiceContext context, ValidationContextSupport validationDataContext, - Map<Class<?>, EntityInterceptor<?, ?>> interceptors, + Map<Class<?>, EntityInterceptor<?, ?, ?>> interceptors, ValidationResultBuilder resultBuilder, MessagesCollector messagesCollector, boolean canWalkInSubclasses) { this.context = context; @@ -140,16 +203,16 @@ public class ValidationMessageDetector { } private <D extends BusinessDto, E extends Entity> void start0(E e) { - EntityInterceptor<D, E> interceptor = getInterceptor(e); + EntityInterceptor<D, E, ?> interceptor = getInterceptor(e); if (interceptor == null) { return; } - LinkedList<ValidationResultDtoMessage> messages = interceptor.intercept(context,messagesCollector, validationDataContext, path, e); + LinkedList<ValidationResultDtoMessage> messages = interceptor.intercept(context, messagesCollector, validationDataContext, path, e); resultBuilder.addMessages(getPath(), messages); } private <D extends BusinessDto, E extends Entity> void end0(E e) { - EntityInterceptor<D, E> interceptor = getInterceptor(e); + EntityInterceptor<D, E, ?> interceptor = getInterceptor(e); if (interceptor == null) { return; } @@ -176,74 +239,11 @@ public class ValidationMessageDetector { } } - public <D extends BusinessDto, E extends Entity> EntityInterceptor<D, E> getInterceptor(E e) { - @SuppressWarnings("unchecked") EntityInterceptor<D, E> interceptor = (EntityInterceptor<D, E>) interceptors.get(e.contractType()); + public <D extends BusinessDto, E extends Entity> EntityInterceptor<D, E, ?> getInterceptor(E e) { + @SuppressWarnings("unchecked") EntityInterceptor<D, E, ?> interceptor = (EntityInterceptor<D, E, ?>) interceptors.get(e.contractType()); return interceptor; } } - - public static ValidationMessageDetector forData(ServiceContext context, - ValidatorsMap validators, - ValidationContextSupport validationDataContext, - IdProject selectModel, - ReferentialLocale referentialLocale, - ValidationResultBuilder resultBuilder) { - Map<Class<?>, EntityInterceptor<?, ?>> interceptors = EntityInterceptors.forData(validators, - validationDataContext, - selectModel, - referentialLocale); - return new ValidationMessageDetector(context, - referentialLocale, - validationDataContext, - resultBuilder, - interceptors, - true); - } - - public static ValidationMessageDetector forReferential(ServiceContext context, - ValidatorsMap validators, - ValidationContextSupport validationDataContext, - ReferentialLocale referentialLocale, - ValidationResultBuilder resultBuilder) { - Map<Class<?>, EntityInterceptor<?, ?>> interceptors = EntityInterceptors.forReferential(validators, - validationDataContext, - referentialLocale); - return new ValidationMessageDetector(context, - referentialLocale, - validationDataContext, - resultBuilder, - interceptors, - false); - } - - private ValidationMessageDetector(ServiceContext context, - ReferentialLocale referentialLocale, - ValidationContextSupport validationDataContext, - ValidationResultBuilder resultBuilder, - Map<Class<?>, EntityInterceptor<?, ?>> interceptors, - boolean canWalkInSubclasses) { - this.entityVisitor = new ValidationEntityVisitor(context, - validationDataContext, - interceptors, - resultBuilder, - new MessagesCollector(referentialLocale.getLocale()), - canWalkInSubclasses); - } - - public <E extends Entity> void detectValidationMessages(E entity) { - try { - entity.accept(entityVisitor); - } finally { - entityVisitor.clear(); - } - } - - public <E extends Entity> void detectValidationMessages(Iterable<E> entities) { - for (E entity : entities) { - entity.accept(entityVisitor); - } - entityVisitor.clear(); - } } ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/DefaultEntityInterceptorCallback.java ===================================== @@ -0,0 +1,48 @@ +package fr.ird.observe.spi.validation.callback; + +/*- + * #%L + * ObServe Toolkit :: Persistence + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.spi.context.DtoEntityContext; +import fr.ird.observe.spi.service.ServiceContext; + +import java.util.Deque; + +/** + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.3.4 + */ +public class DefaultEntityInterceptorCallback<D extends BusinessDto, E extends Entity, S extends DtoEntityContext<D, ?, E, ?>> implements EntityInterceptorCallback<D, E, S> { + @Override + public boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType) { + return true; + } + + @Override + public void loadDtoForValidation(ServiceContext context, Deque<Entity> path, S spi, E e, D dto) { + spi.loadDtoForValidation(context, e, dto); + } +} ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/EdiableEntityInterceptorCallback.java ===================================== @@ -0,0 +1,51 @@ +package fr.ird.observe.spi.validation.callback; + +/*- + * #%L + * ObServe Toolkit :: Persistence + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.dto.data.EditableDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.entities.data.DataEntity; +import fr.ird.observe.spi.context.EditableDtoEntityContext; +import fr.ird.observe.spi.service.ServiceContext; + +import java.util.Deque; + +/** + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.3.4 + */ +public class EdiableEntityInterceptorCallback<D extends EditableDto, E extends DataEntity, S extends EditableDtoEntityContext<Entity, D, ?, E, ?>> implements EntityInterceptorCallback<D, E, S> { + @Override + public boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType) { + return EditableDto.class.isAssignableFrom(dtoType); + } + + @Override + public void loadDtoForValidation(ServiceContext context, Deque<Entity> path, S spi, E e, D dto) { + Entity parent = EntityInterceptorCallback.getParent(path, e, spi.parentSpi().toEntityType()); + spi.loadDtoForValidation(context, parent, e, dto); + } +} ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/EntityInterceptorCallback.java ===================================== @@ -0,0 +1,58 @@ +package fr.ird.observe.spi.validation.callback; + +/*- + * #%L + * ObServe Toolkit :: Persistence + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.spi.context.DtoEntityContext; +import fr.ird.observe.spi.service.ServiceContext; + +import java.util.Deque; +import java.util.List; +import java.util.Objects; + +/** + * To perform extra actions on interception. + * <p> + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @see fr.ird.observe.spi.validation.EntityInterceptor + * @since 9.3.4 + */ +public interface EntityInterceptorCallback<D extends BusinessDto, E extends Entity, S extends DtoEntityContext<D, ?, E, ?>> { + + static <E extends Entity, P extends Entity> P getParent(Deque<Entity> path, E e, Class<P> parentType) { + List<Entity> copy = List.copyOf(path); + int parentPosition = copy.indexOf(e) - 1; + Entity parent = copy.get(parentPosition); + while (!parentType.isAssignableFrom(parent.contractType())) { + parent = copy.get(--parentPosition); + } + return parentType.cast(Objects.requireNonNull(parent, String.format("Could not find parent of type: %s for entity: %s on path: %s", parentType.getName(), e, path))); + } + + boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType); + + void loadDtoForValidation(ServiceContext context, Deque<Entity> path, S spi, E e, D dto); +} ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/EntityInterceptorCallbacks.java ===================================== @@ -0,0 +1,62 @@ +package fr.ird.observe.spi.validation.callback; + +/*- + * #%L + * ObServe Toolkit :: Persistence + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.spi.context.DtoEntityContext; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.LinkedList; +import java.util.List; +import java.util.ServiceLoader; + +/** + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.4.0 + */ +public final class EntityInterceptorCallbacks { + private static final Logger log = LogManager.getLogger(EntityInterceptorCallbacks.class); + + private final List<EntityInterceptorCallback<?, ?, ?>> callbacks; + + public EntityInterceptorCallbacks() { + log.info("Initializing... {}", this); + callbacks = new LinkedList<>(); + for (EntityInterceptorCallback<?, ?, ?> entityInterceptorCallback : ServiceLoader.load(EntityInterceptorCallback.class)) { + callbacks.add(entityInterceptorCallback); + } + callbacks.add(new OpenableEntityInterceptorCallback<>()); + callbacks.add(new EdiableEntityInterceptorCallback<>()); + callbacks.add(new DefaultEntityInterceptorCallback<>()); + log.info("Initialization done {}, register {} EntityInterceptorCallback(s).", this, callbacks.size()); + } + + @SuppressWarnings("unchecked") + public <D extends BusinessDto, E extends Entity, S extends DtoEntityContext<D, ?, E, ?>> EntityInterceptorCallback<D, E, S> getCallback(Class<D> dtoType, Class<E> entityType) { + return (EntityInterceptorCallback<D, E, S>) callbacks.stream().filter(entityInterceptorCallback -> entityInterceptorCallback.acceptType(dtoType, entityType)).findFirst().orElseThrow(() -> new IllegalStateException(String.format("Can't find callback for dto type: %s and entity type: %s", dtoType, entityType))); + } +} ===================================== toolkit/persistence/src/main/java/fr/ird/observe/spi/validation/callback/OpenableEntityInterceptorCallback.java ===================================== @@ -0,0 +1,51 @@ +package fr.ird.observe.spi.validation.callback; + +/*- + * #%L + * ObServe Toolkit :: Persistence + * %% + * Copyright (C) 2008 - 2024 IRD, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import fr.ird.observe.dto.BusinessDto; +import fr.ird.observe.dto.data.OpenableDto; +import fr.ird.observe.entities.Entity; +import fr.ird.observe.entities.data.DataEntity; +import fr.ird.observe.spi.context.OpenableDtoEntityContext; +import fr.ird.observe.spi.service.ServiceContext; + +import java.util.Deque; + +/** + * Created at 21/05/2024. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 9.3.4 + */ +public class OpenableEntityInterceptorCallback<D extends OpenableDto, E extends DataEntity, S extends OpenableDtoEntityContext<Entity, D, ?, E, ?>> implements EntityInterceptorCallback<D, E, S> { + @Override + public boolean acceptType(Class<? extends BusinessDto> dtoType, Class<? extends Entity> entityType) { + return OpenableDto.class.isAssignableFrom(dtoType); + } + + @Override + public void loadDtoForValidation(ServiceContext context, Deque<Entity> path, S spi, E e, D dto) { + Entity parent = EntityInterceptorCallback.getParent(path, e, spi.parentSpi().toEntityType()); + spi.loadDtoForValidation(context, parent, e, dto); + } +} View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/-/compare/f46a8dbc2770035a8a4bffe0f... -- View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/-/compare/f46a8dbc2770035a8a4bffe0f... You're receiving this email because of your account on gitlab.com.