Tony CHEMIT pushed to branch feature/issue-2846 at ultreiaio / ird-observe

Commits:

9 changed files:

Changes:

  • client/datasource/editor/api/src/main/java/fr/ird/observe/client/datasource/editor/api/content/referential/ContentReferentialUIHandler.java
    ... ... @@ -44,11 +44,11 @@ import fr.ird.observe.client.datasource.editor.api.content.referential.actions.S
    44 44
     import fr.ird.observe.client.datasource.editor.api.content.referential.actions.ShowUsagesReferential;
    
    45 45
     import fr.ird.observe.client.util.UIHelper;
    
    46 46
     import fr.ird.observe.datasource.security.ConcurrentModificationException;
    
    47
    -import fr.ird.observe.dto.ToolkitIdLabel;
    
    48 47
     import fr.ird.observe.dto.reference.ReferentialDtoReference;
    
    49 48
     import fr.ird.observe.dto.referential.ReferentialDto;
    
    50 49
     import fr.ird.observe.dto.referential.ReferentialDtoReferenceWithNoCodeAware;
    
    51 50
     import fr.ird.observe.services.service.SaveResultDto;
    
    51
    +import fr.ird.observe.services.service.referential.ExtraSaveRequest;
    
    52 52
     import io.ultreia.java4all.i18n.I18n;
    
    53 53
     import io.ultreia.java4all.jaxx.widgets.list.ListHeader;
    
    54 54
     import org.apache.logging.log4j.LogManager;
    
    ... ... @@ -284,14 +284,8 @@ public class ContentReferentialUIHandler<D extends ReferentialDto, R extends Ref
    284 284
         }
    
    285 285
     
    
    286 286
         protected SaveResultDto doSave(D bean) throws ConcurrentModificationException {
    
    287
    -        ToolkitIdLabel replaceReference = getModel().getStates().getReplaceReference();
    
    288
    -        if (replaceReference != null) {
    
    289
    -            String id = bean.getId();
    
    290
    -            String replaceId = replaceReference.getId();
    
    291
    -            log.info(String.format("Do replace reference before save (%s → %s)", id, replaceId));
    
    292
    -            getReferentialService().replaceReference(getModel().getSource().getScope().getMainType(), id, replaceId);
    
    293
    -        }
    
    294
    -        SaveResultDto result = getReferentialService().save(bean);
    
    287
    +        ExtraSaveRequest request = getModel().getStates().toExtraSaveRequest();
    
    288
    +        SaveResultDto result = getReferentialService().save(bean, request);
    
    295 289
             bean.copy(getModel().getStates().getForm().getObject());
    
    296 290
             return result;
    
    297 291
         }
    

  • client/datasource/editor/api/src/main/java/fr/ird/observe/client/datasource/editor/api/content/referential/ContentReferentialUIModelStates.java
    ... ... @@ -30,6 +30,7 @@ import fr.ird.observe.client.datasource.editor.api.content.ContentUIModel;
    30 30
     import fr.ird.observe.client.datasource.editor.api.content.ContentUIModelStates;
    
    31 31
     import fr.ird.observe.client.datasource.editor.api.content.actions.save.SavePredicate;
    
    32 32
     import fr.ird.observe.client.util.init.DefaultUIInitializerResult;
    
    33
    +import fr.ird.observe.dto.ToolkitIdBean;
    
    33 34
     import fr.ird.observe.dto.ToolkitIdDtoBean;
    
    34 35
     import fr.ird.observe.dto.ToolkitIdLabel;
    
    35 36
     import fr.ird.observe.dto.form.Form;
    
    ... ... @@ -38,11 +39,20 @@ import fr.ird.observe.dto.referential.ReferentialDto;
    38 39
     import fr.ird.observe.dto.referential.ReferentialLocale;
    
    39 40
     import fr.ird.observe.navigation.id.Project;
    
    40 41
     import fr.ird.observe.services.ObserveServicesProvider;
    
    42
    +import fr.ird.observe.services.service.referential.ExtraSaveRequest;
    
    43
    +import org.apache.logging.log4j.LogManager;
    
    44
    +import org.apache.logging.log4j.Logger;
    
    41 45
     
    
    42 46
     import javax.swing.ListModel;
    
    47
    +import java.util.Collection;
    
    48
    +import java.util.LinkedHashMap;
    
    43 49
     import java.util.LinkedList;
    
    44 50
     import java.util.List;
    
    51
    +import java.util.Map;
    
    45 52
     import java.util.Objects;
    
    53
    +import java.util.Optional;
    
    54
    +import java.util.Set;
    
    55
    +import java.util.stream.Collectors;
    
    46 56
     
    
    47 57
     /**
    
    48 58
      * Created on 30/10/2020.
    
    ... ... @@ -52,6 +62,7 @@ import java.util.Objects;
    52 62
      */
    
    53 63
     public abstract class ContentReferentialUIModelStates<D extends ReferentialDto, R extends ReferentialDtoReference> extends ContentUIModelStates {
    
    54 64
         public static final String PROPERTY_SELECTED_BEAN_REFERENCE = "selectedBeanReference";
    
    65
    +    private static final Logger log = LogManager.getLogger(ContentReferentialUIModelStates.class);
    
    55 66
         /**
    
    56 67
          * Reference cache.
    
    57 68
          */
    
    ... ... @@ -67,6 +78,12 @@ public abstract class ContentReferentialUIModelStates<D extends ReferentialDto,
    67 78
         private Form<D> form;
    
    68 79
         private ToolkitIdLabel replaceReference;
    
    69 80
         private ContentReferentialUI<D, R, ?> ui;
    
    81
    +    /**
    
    82
    +     * To keep the second level usages when necessary).
    
    83
    +     *
    
    84
    +     * @since 9.4.0
    
    85
    +     */
    
    86
    +    private Map<Class<? extends ReferentialDto>, Collection<ToolkitIdLabel>> secondLevelUsages;
    
    70 87
     
    
    71 88
         public ContentReferentialUIModelStates(ContentReferentialUIModel<D, R> model, D bean) {
    
    72 89
             source = Objects.requireNonNull(model).getSource();
    
    ... ... @@ -194,7 +211,45 @@ public abstract class ContentReferentialUIModelStates<D extends ReferentialDto,
    194 211
             return mainType;
    
    195 212
         }
    
    196 213
     
    
    214
    +    public ExtraSaveRequest toExtraSaveRequest() {
    
    215
    +        ToolkitIdLabel replaceReference = getReplaceReference();
    
    216
    +        if (replaceReference != null) {
    
    217
    +            String id = bean.getId();
    
    218
    +            String replaceId = replaceReference.getId();
    
    219
    +            log.info("Do replace reference before save ({} → {})", id, replaceId);
    
    220
    +        }
    
    221
    +        Map<Class<? extends ReferentialDto>, Set<String>> toDisableIds = getToDisableIds();
    
    222
    +        if (toDisableIds != null) {
    
    223
    +            toDisableIds.forEach((k, v) -> log.info("Do disable references before save of type {} → {} id(s)", k, v.size()));
    
    224
    +        }
    
    225
    +        String replaceId = Optional.ofNullable(replaceReference).map(ToolkitIdBean::getId).orElse(null);
    
    226
    +        if (replaceId == null && toDisableIds == null) {
    
    227
    +            return null;
    
    228
    +        }
    
    229
    +        return new ExtraSaveRequest(replaceId, toDisableIds);
    
    230
    +    }
    
    231
    +
    
    232
    +    private Map<Class<? extends ReferentialDto>, Set<String>> getToDisableIds() {
    
    233
    +        Map<Class<? extends ReferentialDto>, Collection<ToolkitIdLabel>> secondLevelUsages = getSecondLevelUsages();
    
    234
    +        Map<Class<? extends ReferentialDto>, Set<String>> toDisableIds;
    
    235
    +        if (secondLevelUsages == null) {
    
    236
    +            toDisableIds = null;
    
    237
    +        } else {
    
    238
    +            toDisableIds = new LinkedHashMap<>(secondLevelUsages.size());
    
    239
    +            secondLevelUsages.forEach((k, v) -> toDisableIds.put(k, v.stream().map(ToolkitIdBean::getId).collect(Collectors.toSet())));
    
    240
    +        }
    
    241
    +        return toDisableIds;
    
    242
    +    }
    
    243
    +
    
    197 244
         public Class<R> mainReferenceType() {
    
    198 245
             return mainReferenceType;
    
    199 246
         }
    
    247
    +
    
    248
    +    public Map<Class<? extends ReferentialDto>, Collection<ToolkitIdLabel>> getSecondLevelUsages() {
    
    249
    +        return secondLevelUsages;
    
    250
    +    }
    
    251
    +
    
    252
    +    public void setSecondLevelUsages(Map<Class<? extends ReferentialDto>, Collection<ToolkitIdLabel>> secondLevelUsages) {
    
    253
    +        this.secondLevelUsages = secondLevelUsages;
    
    254
    +    }
    
    200 255
     }

  • client/datasource/editor/api/src/main/java/fr/ird/observe/client/datasource/editor/api/content/referential/ReferentialSavePredicate.java
    ... ... @@ -24,16 +24,28 @@ package fr.ird.observe.client.datasource.editor.api.content.referential;
    24 24
     
    
    25 25
     import fr.ird.observe.client.datasource.editor.api.content.actions.save.SavePredicateSupport;
    
    26 26
     import fr.ird.observe.client.datasource.editor.api.content.referential.usage.UsageForDesactivateUIHandler;
    
    27
    +import fr.ird.observe.dto.BusinessDto;
    
    27 28
     import fr.ird.observe.dto.ToolkitIdDtoBean;
    
    28 29
     import fr.ird.observe.dto.ToolkitIdLabel;
    
    29 30
     import fr.ird.observe.dto.reference.ReferentialDtoReference;
    
    30 31
     import fr.ird.observe.dto.referential.ReferenceStatus;
    
    31 32
     import fr.ird.observe.dto.referential.ReferentialDto;
    
    32 33
     import fr.ird.observe.services.service.UsageCount;
    
    34
    +import fr.ird.observe.services.service.UsageCountWithLabel;
    
    33 35
     import fr.ird.observe.services.service.UsageService;
    
    36
    +import fr.ird.observe.services.service.referential.ObserveReferentialSecondLevelDeepBehaviourModel;
    
    37
    +import fr.ird.observe.spi.module.ObserveBusinessProject;
    
    38
    +import io.ultreia.java4all.i18n.I18n;
    
    34 39
     import org.apache.commons.lang3.tuple.Pair;
    
    40
    +import org.apache.logging.log4j.LogManager;
    
    41
    +import org.apache.logging.log4j.Logger;
    
    35 42
     
    
    43
    +import java.util.Collection;
    
    44
    +import java.util.LinkedHashMap;
    
    36 45
     import java.util.List;
    
    46
    +import java.util.Map;
    
    47
    +import java.util.Objects;
    
    48
    +import java.util.Set;
    
    37 49
     import java.util.stream.Collectors;
    
    38 50
     
    
    39 51
     /**
    
    ... ... @@ -43,7 +55,7 @@ import java.util.stream.Collectors;
    43 55
      * @since 9.0.0
    
    44 56
      */
    
    45 57
     public class ReferentialSavePredicate<D extends ReferentialDto, R extends ReferentialDtoReference, S extends ContentReferentialUIModelStates<D, R>> extends SavePredicateSupport<S,D> {
    
    46
    -
    
    58
    +    private static final Logger log = LogManager.getLogger(ReferentialSavePredicate.class);
    
    47 59
         public ReferentialSavePredicate(S states) {
    
    48 60
             super(states);
    
    49 61
         }
    
    ... ... @@ -66,26 +78,51 @@ public class ReferentialSavePredicate<D extends ReferentialDto, R extends Refere
    66 78
                 ToolkitIdDtoBean request = states.toUsageRequest(bean.getId());
    
    67 79
                 UsageCount usages = usageService.countReferential(request);
    
    68 80
     
    
    69
    -            if (!usages.isEmpty()) {
    
    70
    -                // some usages were found
    
    81
    +            if (usages.isEmpty()) {
    
    82
    +                return true;
    
    83
    +            }
    
    71 84
     
    
    72
    -                // get replacements
    
    73
    -                List<R> referentialReferences = states.getReferentialReferences();
    
    74
    -                List<R> referenceList = referentialReferences
    
    75
    -                        .stream()
    
    76
    -                        .filter(ReferentialDtoReference::isEnabled)
    
    77
    -                        .filter(r -> !bean.getId().equals(r.getId()))
    
    78
    -                        .collect(Collectors.toList());
    
    85
    +            // some usages were found
    
    86
    +            UsageCountWithLabel realUsages = new UsageCountWithLabel(I18n.getDefaultLocale(), ObserveBusinessProject.get(), usages);
    
    87
    +            UsageForDesactivateUIHandler.DisableReferentialUsagesGetter getter = new UsageForDesactivateUIHandler.DisableReferentialUsagesGetter(realUsages, usageService, request);
    
    79 88
     
    
    80
    -                ToolkitIdLabel dtoLabel = bean.toLabel();
    
    81
    -                states.getDecoratorService().installToolkitIdLabelDecorator(bean.getClass(), dtoLabel);
    
    82
    -                Pair<Boolean, ToolkitIdLabel> result = UsageForDesactivateUIHandler.showUsages(usageService, dtoLabel, request, usages, referenceList.stream().map(ReferentialDtoReference::toLabel).collect(Collectors.toList()));
    
    83
    -                boolean willSave = result.getLeft();
    
    84
    -                if (!willSave) {
    
    85
    -                    return false;
    
    89
    +            ObserveReferentialSecondLevelDeepBehaviourModel referentialSecondLevelDeepBehaviourModel = ObserveReferentialSecondLevelDeepBehaviourModel.get();
    
    90
    +            Map<Class<? extends ReferentialDto>, Collection<ToolkitIdLabel>> secondLevelUsages = new LinkedHashMap<>();
    
    91
    +            Set<Class<? extends BusinessDto>> typesFound = usages.keySet();
    
    92
    +            for (Class<? extends BusinessDto> type : typesFound) {
    
    93
    +                if (!ReferentialDto.class.isAssignableFrom(type)  ) {
    
    94
    +                    continue;
    
    86 95
                     }
    
    87
    -                states.setReplaceReference(result.getRight());
    
    96
    +                @SuppressWarnings("unchecked") Class<? extends ReferentialDto> referentialType = (Class<? extends ReferentialDto>) type;
    
    97
    +                if (referentialSecondLevelDeepBehaviourModel.useSecondLevelDeepBehaviour(referentialType)) {
    
    98
    +                    Collection<ToolkitIdLabel> toolkitIdLabels = getter.getUsages(type).get();
    
    99
    +                    log.info("Found second level type: {} - {} occurrence(s).", referentialType, toolkitIdLabels.size());
    
    100
    +                    secondLevelUsages.put(referentialType,toolkitIdLabels);
    
    101
    +                }
    
    102
    +            }
    
    103
    +            if (!secondLevelUsages.isEmpty()) {
    
    104
    +                states.setSecondLevelUsages(secondLevelUsages);
    
    105
    +            }
    
    106
    +
    
    107
    +            // get replacements
    
    108
    +            List<R> referentialReferences = states.getReferentialReferences();
    
    109
    +            List<ToolkitIdLabel> referenceList = referentialReferences
    
    110
    +                    .stream()
    
    111
    +                    .filter(ReferentialDtoReference::isEnabled)
    
    112
    +                    .filter(r -> !Objects.equals(bean.getId(), r.getId()))
    
    113
    +                    .map(ReferentialDtoReference::toLabel)
    
    114
    +                    .collect(Collectors.toList());
    
    115
    +
    
    116
    +            ToolkitIdLabel dtoLabel = bean.toLabel();
    
    117
    +            states.getDecoratorService().installToolkitIdLabelDecorator(bean.getClass(), dtoLabel);
    
    118
    +            Pair<Boolean, ToolkitIdLabel> result = UsageForDesactivateUIHandler.showUsages(dtoLabel,
    
    119
    +                                                                                           getter,
    
    120
    +                                                                                           referenceList);
    
    121
    +            boolean willSave = result.getLeft();
    
    122
    +            if (!willSave) {
    
    123
    +                return false;
    
    88 124
                 }
    
    125
    +            states.setReplaceReference(result.getRight());
    
    89 126
             }
    
    90 127
             return true;
    
    91 128
         }
    

  • client/datasource/editor/api/src/main/java/fr/ird/observe/client/datasource/editor/api/content/referential/usage/UsageForDesactivateUIHandler.java
    ... ... @@ -29,12 +29,10 @@ import fr.ird.observe.client.util.init.UIInitHelper;
    29 29
     import fr.ird.observe.dto.BusinessDto;
    
    30 30
     import fr.ird.observe.dto.ToolkitIdDtoBean;
    
    31 31
     import fr.ird.observe.dto.ToolkitIdLabel;
    
    32
    -import fr.ird.observe.services.service.UsageCount;
    
    33 32
     import fr.ird.observe.services.service.UsageCountWithLabel;
    
    34 33
     import fr.ird.observe.services.service.UsageService;
    
    35 34
     import fr.ird.observe.spi.module.ObserveBusinessProject;
    
    36 35
     import io.ultreia.java4all.application.template.spi.GenerateTemplate;
    
    37
    -import io.ultreia.java4all.i18n.I18n;
    
    38 36
     import io.ultreia.java4all.jaxx.widgets.combobox.FilterableComboBox;
    
    39 37
     import io.ultreia.java4all.jaxx.widgets.combobox.FilterableComboBoxModel;
    
    40 38
     import io.ultreia.java4all.util.SingletonSupplier;
    
    ... ... @@ -85,15 +83,10 @@ public class UsageForDesactivateUIHandler extends UsageUIHandlerSupport<UsageFor
    85 83
             }
    
    86 84
         }
    
    87 85
     
    
    88
    -    public static Pair<Boolean, ToolkitIdLabel> showUsages(UsageService usageService,
    
    89
    -                                                           ToolkitIdLabel dto,
    
    90
    -                                                           ToolkitIdDtoBean request,
    
    91
    -                                                           UsageCount usages,
    
    86
    +    public static Pair<Boolean, ToolkitIdLabel> showUsages(ToolkitIdLabel dto,
    
    87
    +                                                           DisableReferentialUsagesGetter getter,
    
    92 88
                                                                List<ToolkitIdLabel> referenceList) {
    
    93 89
             ObserveBusinessProject businessProject = ObserveBusinessProject.get();
    
    94
    -        UsageCountWithLabel realUsages = new UsageCountWithLabel(I18n.getDefaultLocale(), businessProject, usages);
    
    95
    -        DisableReferentialUsagesGetter getter = new DisableReferentialUsagesGetter(realUsages, usageService, request);
    
    96
    -
    
    97 90
             Class<? extends BusinessDto> dtoType = dto.getType();
    
    98 91
             String type = businessProject.getLongTitle(dtoType);
    
    99 92
             String message = t("observe.ui.message.show.usage.referential.disabled", type, dto);
    

  • core/persistence/java/src/main/java/fr/ird/observe/entities/referential/common/OceanSpi.java
    ... ... @@ -28,6 +28,7 @@ import fr.ird.observe.dto.referential.common.SpeciesReference;
    28 28
     import fr.ird.observe.services.service.SaveResultDto;
    
    29 29
     import fr.ird.observe.spi.result.AddEntityToUpdateStep;
    
    30 30
     import fr.ird.observe.spi.service.ServiceContext;
    
    31
    +import io.ultreia.java4all.util.sql.SqlScript;
    
    31 32
     
    
    32 33
     import java.util.LinkedHashSet;
    
    33 34
     import java.util.List;
    
    ... ... @@ -54,7 +55,7 @@ public class OceanSpi extends GeneratedOceanSpi {
    54 55
         }
    
    55 56
     
    
    56 57
         @Override
    
    57
    -    public SaveResultDto saveEntity(ServiceContext context, Ocean entity, OceanDto dto) {
    
    58
    +    public SaveResultDto saveEntity(ServiceContext context, Ocean entity, OceanDto dto, List<SqlScript> extraScripts) {
    
    58 59
             Set<Species> speciesToUpdate = new LinkedHashSet<>();
    
    59 60
             Set<String> newSpeciesWithThisOceanIds = dto.getSpecies().stream().map(SpeciesReference::getId).collect(Collectors.toSet());
    
    60 61
             if (dto.isPersisted()) {
    
    ... ... @@ -87,6 +88,6 @@ public class OceanSpi extends GeneratedOceanSpi {
    87 88
             for (Species species : speciesToUpdate) {
    
    88 89
                 update.update(Species.SPI, species);
    
    89 90
             }
    
    90
    -        return update.build(entity);
    
    91
    +        return update.addExtraSqlScripts(extraScripts).build(entity);
    
    91 92
         }
    
    92
    -} //OceanSpi
    93
    +}

  • core/services/local/src/main/java/fr/ird/observe/services/local/service/referential/ReferentialServiceLocalSupport.java
    ... ... @@ -31,6 +31,7 @@ import fr.ird.observe.dto.reference.ReferentialDtoReferenceSet;
    31 31
     import fr.ird.observe.dto.referential.ReferentialDto;
    
    32 32
     import fr.ird.observe.services.local.service.ObserveServiceLocal;
    
    33 33
     import fr.ird.observe.services.service.SaveResultDto;
    
    34
    +import fr.ird.observe.services.service.referential.ExtraSaveRequest;
    
    34 35
     import fr.ird.observe.services.service.referential.ReferentialIds;
    
    35 36
     import fr.ird.observe.services.service.referential.ReferentialService;
    
    36 37
     import fr.ird.observe.spi.context.ReferentialDtoEntityContext;
    
    ... ... @@ -85,10 +86,10 @@ class ReferentialServiceLocalSupport extends ObserveServiceLocal implements Refe
    85 86
         }
    
    86 87
     
    
    87 88
         @Override
    
    88
    -    public <D extends ReferentialDto> SaveResultDto save(D bean) throws ConcurrentModificationException {
    
    89
    +    public <D extends ReferentialDto> SaveResultDto save(D bean, ExtraSaveRequest extraSaveRequest) throws ConcurrentModificationException {
    
    89 90
             @SuppressWarnings("unchecked") Class<D> type = (Class<D>) bean.getClass();
    
    90 91
             ReferentialDtoEntityContext<D, ?, ?, ?> spi = fromReferentialDto(type);
    
    91
    -        return spi.save(this, bean);
    
    92
    +        return spi.save(this, bean, extraSaveRequest);
    
    92 93
         }
    
    93 94
     
    
    94 95
         @Override
    

  • core/services/local/src/test/java/fr/ird/observe/services/local/service/referential/UnidirectionalResultIssue2208Test.java
    ... ... @@ -31,6 +31,7 @@ import fr.ird.observe.dto.referential.common.SpeciesDto;
    31 31
     import fr.ird.observe.services.local.LocalTestClassResource;
    
    32 32
     import fr.ird.observe.services.local.LocalTestMethodResourceWrite;
    
    33 33
     import fr.ird.observe.services.local.service.ServiceLocalTestSupportWrite;
    
    34
    +import fr.ird.observe.services.service.referential.ExtraSaveRequest;
    
    34 35
     import fr.ird.observe.services.service.referential.ReferentialService;
    
    35 36
     import fr.ird.observe.services.service.referential.ReferentialServiceFixtures;
    
    36 37
     import fr.ird.observe.services.service.referential.SynchronizeEngine;
    
    ... ... @@ -121,7 +122,7 @@ public class UnidirectionalResultIssue2208Test extends ServiceLocalTestSupportWr
    121 122
             centralSpecies.getOcean().add(ocean);
    
    122 123
             TOPIA_TEST_CLASS_RESOURCE_CENTRAL.setGenerateNow(true);
    
    123 124
             try {
    
    124
    -            centralReferentialService.save(centralSpecies);
    
    125
    +            centralReferentialService.save(centralSpecies, null);
    
    125 126
             } finally {
    
    126 127
                 TOPIA_TEST_CLASS_RESOURCE_CENTRAL.setGenerateNow(false);
    
    127 128
             }
    

  • core/services/test/src/main/java/fr/ird/observe/services/service/referential/ReferentialServiceFixtures.java
    ... ... @@ -189,7 +189,7 @@ public class ReferentialServiceFixtures extends GeneratedReferentialServiceFixtu
    189 189
             fr.ird.observe.dto.referential.ps.common.ProgramDto actual = service.loadDto(fr.ird.observe.dto.referential.ps.common.ProgramDto.class, getProperty("loadDto.id"));
    
    190 190
             Assert.assertNotNull(actual);
    
    191 191
             try {
    
    192
    -            SaveResultDto actualResult = service.save(actual);
    
    192
    +            SaveResultDto actualResult = service.save(actual, null);
    
    193 193
                 Assert.assertNotNull(actualResult);
    
    194 194
             } catch (ConcurrentModificationException e) {
    
    195 195
                 throw new RuntimeException(e);
    

  • toolkit/persistence/src/main/java/fr/ird/observe/spi/context/ReferentialDtoEntityContext.java
    ... ... @@ -40,6 +40,7 @@ import fr.ird.observe.entities.referential.I18nReferentialEntity;
    40 40
     import fr.ird.observe.entities.referential.ReferentialEntity;
    
    41 41
     import fr.ird.observe.services.service.SaveResultDto;
    
    42 42
     import fr.ird.observe.services.service.UsageCount;
    
    43
    +import fr.ird.observe.services.service.referential.ExtraSaveRequest;
    
    43 44
     import fr.ird.observe.spi.referential.ReferentialExtraScripts;
    
    44 45
     import fr.ird.observe.spi.service.ServiceContext;
    
    45 46
     import fr.ird.observe.spi.usage.UsageHelper;
    
    ... ... @@ -52,10 +53,11 @@ import org.nuiton.topia.persistence.TopiaEntity;
    52 53
     import org.nuiton.topia.persistence.TopiaException;
    
    53 54
     import org.nuiton.topia.service.sql.script.DeleteReferentialScript;
    
    54 55
     import org.nuiton.topia.service.sql.script.DisableReferentialScript;
    
    55
    -import org.nuiton.topia.service.sql.script.ReplaceReferentialInReferentialScript;
    
    56 56
     import org.nuiton.topia.service.sql.script.ReplaceReferentialInDataScript;
    
    57
    +import org.nuiton.topia.service.sql.script.ReplaceReferentialInReferentialScript;
    
    57 58
     import org.nuiton.topia.service.sql.script.TopiaEntitySqlScript;
    
    58 59
     
    
    60
    +import java.sql.Timestamp;
    
    59 61
     import java.util.ArrayList;
    
    60 62
     import java.util.Collection;
    
    61 63
     import java.util.Comparator;
    
    ... ... @@ -83,23 +85,22 @@ public abstract class ReferentialDtoEntityContext<
    83 85
     
    
    84 86
         private final SingletonSupplier<ReferentialExtraScripts<E>> extraScripts;
    
    85 87
     
    
    86
    -    protected abstract TopiaEntitySqlScript loadSqlScript();
    
    87
    -
    
    88
    -
    
    89
    -    protected abstract ReferentialExtraScripts<E> loadExtraScripts();
    
    90
    -
    
    91 88
         public ReferentialDtoEntityContext() {
    
    92 89
             this.extraScripts = SingletonSupplier.of(this::loadExtraScripts);
    
    93 90
         }
    
    94 91
     
    
    92
    +    protected abstract TopiaEntitySqlScript loadSqlScript();
    
    93
    +
    
    94
    +    protected abstract ReferentialExtraScripts<E> loadExtraScripts();
    
    95
    +
    
    95 96
         @Override
    
    96 97
         public Form<D> loadForm(ServiceContext context, String id) {
    
    97 98
             E entity = loadEntity(context, id);
    
    98 99
             return referentialEntityToForm(context.getReferentialLocale(), entity);
    
    99 100
         }
    
    100 101
     
    
    101
    -    public SaveResultDto saveEntity(ServiceContext context, E entity, D dto) {
    
    102
    -        return saveEntity(context, entity);
    
    102
    +    public SaveResultDto saveEntity(ServiceContext context, E entity, D dto, List<SqlScript> extraScripts) {
    
    103
    +        return newSaveHelper(context).update(this, entity).addExtraSqlScripts(extraScripts).build(entity);
    
    103 104
         }
    
    104 105
     
    
    105 106
         public Optional<ReplaceReferentialInDataScript> getReplaceInDataScript() {
    
    ... ... @@ -261,6 +262,15 @@ public abstract class ReferentialDtoEntityContext<
    261 262
             sqlScript.ifPresent(s -> context.getTopiaPersistenceContext().executeSqlScript(s));
    
    262 263
         }
    
    263 264
     
    
    265
    +    public final Optional<SqlScript> replaceReferenceScript(ServiceContext context, String idToReplace, String replaceId, boolean replaceInReferential, boolean replaceInData) {
    
    266
    +        if (!replaceInReferential && !replaceInData) {
    
    267
    +            throw new IllegalStateException("Need at least one of the parameters *replaceInReferential* or *replaceInData* to be on.");
    
    268
    +        }
    
    269
    +        checkEntityExists(context, idToReplace);
    
    270
    +        checkEntityExists(context, replaceId);
    
    271
    +        return generateReplaceScript(idToReplace, replaceId, context.now(), replaceInReferential, replaceInData);
    
    272
    +    }
    
    273
    +
    
    264 274
         public final void changeId(ServiceContext context, String id, String newId) {
    
    265 275
             checkEntityExists(context, id);
    
    266 276
             log.info(String.format("will change id from %s to %s", id, newId));
    
    ... ... @@ -284,11 +294,33 @@ public abstract class ReferentialDtoEntityContext<
    284 294
     //        delete(context, id);
    
    285 295
         }
    
    286 296
     
    
    287
    -    public final SaveResultDto save(ServiceContext context, D dto) throws ConcurrentModificationException {
    
    297
    +    public final SaveResultDto save(ServiceContext context, D dto, ExtraSaveRequest extraSaveRequest) throws ConcurrentModificationException {
    
    288 298
             E entity = loadOrCreateEntityFromReferentialDto(context, dto);
    
    289 299
             checkLastUpdateDate(context, entity, dto);
    
    300
    +        // if replace id is here, let's do the replacement in data (never replace in referential)
    
    301
    +        List<SqlScript> extraScripts = new ArrayList<>();
    
    302
    +        if (extraSaveRequest != null) {
    
    303
    +            extraSaveRequest.getReplaceId().ifPresent(replaceId -> {
    
    304
    +                Optional<SqlScript> sqlScript = replaceReferenceScript(context, dto.getId(), replaceId, false, true);
    
    305
    +                sqlScript.ifPresent(extraScripts::add);
    
    306
    +            });
    
    307
    +            Timestamp timestamp = context.timestampNow();
    
    308
    +            extraSaveRequest.getToDisableIds().ifPresent(toDisableIds -> {
    
    309
    +                // if toDisableIds is here, let's do the disable actions
    
    310
    +                List<String> sqlStatements = new ArrayList<>();
    
    311
    +                toDisableIds.forEach((k, v) -> {
    
    312
    +                    ReferentialDtoEntityContext<? extends ReferentialDto, ?, ?, ?> spi2 = context.fromReferentialDto(k);
    
    313
    +                    DisableReferentialScript disableScript = spi2.getDisableScript();
    
    314
    +                    v.forEach(id -> sqlStatements.addAll(disableScript.generate(id, timestamp)));
    
    315
    +                    sqlStatements.addAll(spi2.updateLastUpdateDateTable(context.getTopiaPersistenceContext(), timestamp));
    
    316
    +                });
    
    317
    +                if (!sqlStatements.isEmpty()) {
    
    318
    +                    extraScripts.add(SqlScript.of(String.join("\n", sqlStatements)));
    
    319
    +                }
    
    320
    +            });
    
    321
    +        }
    
    290 322
             fromDto(context.getReferentialLocale(), entity, dto);
    
    291
    -        return saveEntity(context, entity, dto);
    
    323
    +        return saveEntity(context, entity, dto, extraScripts);
    
    292 324
         }
    
    293 325
     
    
    294 326
         private SqlScript generateDuplicateScript(ServiceContext context, String id, String newId) {
    
    ... ... @@ -357,10 +389,6 @@ public abstract class ReferentialDtoEntityContext<
    357 389
             return toReference(context.getReferentialLocale(), entity);
    
    358 390
         }
    
    359 391
     
    
    360
    -    public final SaveResultDto saveEntity(ServiceContext context, E entity) {
    
    361
    -        return newSaveHelper(context).update(this, entity).build(entity);
    
    362
    -    }
    
    363
    -
    
    364 392
         public final UsageCount count(ServiceContext context, ToolkitIdDtoBean request) {
    
    365 393
             ReferentialEntity entity = loadEntity(context, request.getId());
    
    366 394
             return newUsageHelper(context).count(entity);