Project

General

Profile

Download (34.4 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.vaadin.view.registration;
10

    
11
import java.util.ArrayList;
12
import java.util.Arrays;
13
import java.util.Collection;
14
import java.util.EnumSet;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Objects;
20
import java.util.Optional;
21
import java.util.Set;
22
import java.util.Stack;
23
import java.util.UUID;
24

    
25
import org.apache.log4j.Logger;
26
import org.springframework.beans.factory.annotation.Autowired;
27
import org.vaadin.spring.events.EventScope;
28
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
29

    
30
import com.vaadin.spring.annotation.SpringComponent;
31
import com.vaadin.spring.annotation.ViewScope;
32
import com.vaadin.ui.AbstractField;
33
import com.vaadin.ui.Label;
34
import com.vaadin.ui.UI;
35
import com.vaadin.ui.VerticalLayout;
36
import com.vaadin.ui.Window;
37

    
38
import eu.etaxonomy.cdm.api.service.config.RegistrationStatusTransitions;
39
import eu.etaxonomy.cdm.api.service.dto.RegistrationDTO;
40
import eu.etaxonomy.cdm.api.service.dto.RegistrationWorkingSet;
41
import eu.etaxonomy.cdm.api.service.exception.RegistrationValidationException;
42
import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager.TypeDesignationWorkingSetType;
43
import eu.etaxonomy.cdm.api.service.registration.IRegistrationWorkingSetService;
44
import eu.etaxonomy.cdm.api.utility.UserHelper;
45
import eu.etaxonomy.cdm.cache.CdmTransientEntityAndUuidCacher;
46
import eu.etaxonomy.cdm.database.PermissionDeniedException;
47
import eu.etaxonomy.cdm.model.ICdmEntityUuidCacher;
48
import eu.etaxonomy.cdm.model.common.CdmBase;
49
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
50
import eu.etaxonomy.cdm.model.name.Rank;
51
import eu.etaxonomy.cdm.model.name.Registration;
52
import eu.etaxonomy.cdm.model.name.RegistrationStatus;
53
import eu.etaxonomy.cdm.model.name.TaxonName;
54
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
55
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
56
import eu.etaxonomy.cdm.model.reference.Reference;
57
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
58
import eu.etaxonomy.cdm.ref.EntityReference;
59
import eu.etaxonomy.cdm.ref.TypedEntityReference;
60
import eu.etaxonomy.cdm.service.CdmBeanItemContainerFactory;
61
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
62
import eu.etaxonomy.cdm.service.CdmFilterablePagingProviderFactory;
63
import eu.etaxonomy.cdm.service.CdmStore;
64
import eu.etaxonomy.cdm.service.IRegistrationWorkflowService;
65
import eu.etaxonomy.cdm.service.UserHelperAccess;
66
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationItem;
67
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStatusFieldInstantiator;
68
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStatusSelect;
69
import eu.etaxonomy.cdm.vaadin.event.EditorActionContext;
70
import eu.etaxonomy.cdm.vaadin.event.EditorActionTypeFilter;
71
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
72
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
73
import eu.etaxonomy.cdm.vaadin.event.RegistrationEditorAction;
74
import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEvent;
75
import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEventEntityTypeFilter;
76
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
77
import eu.etaxonomy.cdm.vaadin.event.TypeDesignationWorkingsetEditorAction;
78
import eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkingsetAction;
79
import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
80
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
81
import eu.etaxonomy.cdm.vaadin.ui.config.TaxonNamePopupEditorConfig;
82
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
83
import eu.etaxonomy.cdm.vaadin.view.name.CachingPresenter;
84
import eu.etaxonomy.cdm.vaadin.view.name.NameTypeDesignationPopupEditor;
85
import eu.etaxonomy.cdm.vaadin.view.name.SpecimenTypeDesignationWorkingsetPopupEditor;
86
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNameEditorPresenter;
87
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditor;
88
import eu.etaxonomy.cdm.vaadin.view.name.TypeDesignationWorkingsetEditorIdSet;
89
import eu.etaxonomy.cdm.vaadin.view.reference.ReferencePopupEditor;
90
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
91
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
92
import eu.etaxonomy.vaadin.mvp.AbstractView;
93
import eu.etaxonomy.vaadin.mvp.BeanInstantiator;
94
import eu.etaxonomy.vaadin.ui.navigation.NavigationEvent;
95
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
96
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent.Reason;
97

    
98
/**
99
 * @author a.kohlbecker
100
 * @since Mar 3, 2017
101
 *
102
 */
103
@SpringComponent
104
@ViewScope
105
public class RegistrationWorkingsetPresenter extends AbstractPresenter<RegistrationWorkingsetView> implements CachingPresenter {
106

    
107
    private static final Logger logger = Logger.getLogger(RegistrationWorkingsetPresenter.class);
108

    
109
    private static final long serialVersionUID = 1L;
110

    
111
    @Autowired
112
    private IRegistrationWorkingSetService regWorkingSetService;
113

    
114
    @Autowired
115
    private IRegistrationWorkflowService registrationWorkflowService;
116

    
117
    @Autowired
118
    private CdmFilterablePagingProviderFactory pagingProviderFactory;
119

    
120
    @Autowired
121
    private CdmBeanItemContainerFactory selectFieldFactory;
122

    
123
    @Autowired
124
    private CdmStore cdmStore;
125

    
126
    /**
127
     * @return the regWorkingSetService
128
     */
129
    public IRegistrationWorkingSetService getWorkingSetService() {
130
        return regWorkingSetService;
131
    }
132

    
133
    private RegistrationWorkingSet workingset;
134

    
135
    /**
136
     * Contains the poupeditor which has been opened to start the registration of a new name as long as it has not been saved or canceled.
137
     * There can always only be one popup editor for this purpose.
138
     */
139
    private TaxonNamePopupEditor newNameForRegistrationPopupEditor = null;
140

    
141
    /**
142
     * Contains
143
     */
144
    private List<Registration> newNameBlockingRegistrations = new ArrayList<>();
145

    
146
    /**
147
     * TODO is this still needed? The regitration UUID should be accessible in the popup editor context,
148
     * see findRegistrationInContext()
149
     */
150
    private Map<NameTypeDesignationPopupEditor, UUID> nameTypeDesignationPopupEditorRegistrationUUIDMap = new HashMap<>();
151

    
152

    
153
    private ICdmEntityUuidCacher cache;
154

    
155
    private Collection<CdmBase> rootEntities = new HashSet<>();
156

    
157
    /**
158
     *
159
     */
160
    public RegistrationWorkingsetPresenter() {
161
    }
162

    
163
    /**
164

    
165

    
166
    /**
167
     * @param doReload reload the workingset from the persistent storage.
168
     *  Workingsets which are not yet persisted are preserved.
169
     *
170
     */
171
    protected void refreshView(boolean doReload) {
172
        if(workingset == null){
173
            return; // nothing to do
174
        }
175
        if(doReload){
176
            List<RegistrationDTO> unpersisted = new ArrayList<>();
177
            for(RegistrationDTO regDto : workingset.getRegistrationDTOs()){
178
                if(!regDto.registration().isPersited()){
179
                    unpersisted.add(regDto);
180
                }
181
            }
182
            loadWorkingSet(workingset.getCitationUuid());
183
            for(RegistrationDTO regDtoUnpersisted : unpersisted){
184
                if(!workingset.getRegistrationDTOs().stream().anyMatch(dto -> dto.getUuid().equals(regDtoUnpersisted.getUuid()))){
185
                    // only add if the regDtoUnpersisted has not been persisted meanwhile
186
                    try {
187
                        workingset.add(regDtoUnpersisted);
188
                    } catch (RegistrationValidationException e) {
189
                        // would never happen here //
190
                    }
191
                }
192
            }
193
        }
194
        applyWorkingset();
195
    }
196

    
197
    /**
198
     * {@inheritDoc}
199
     */
200
    @Override
201
    public void handleViewEntered() {
202
        super.handleViewEntered();
203
        // TODO currently cannot specify type more precisely, see AbstractSelect
204
        // FIXME externalize into class file!!!!!!!!!!!!
205
        getView().setStatusComponentInstantiator(new RegistrationStatusFieldInstantiator<Object>(){
206

    
207
            private static final long serialVersionUID = 7099181280977511048L;
208

    
209
            @Override
210
            public AbstractField<Object> create(RegistrationDTO regDto) {
211

    
212
                // submitters have GrantedAuthorities like REGISTRATION(PREPARATION).[UPDATE]{ab4459eb-3b96-40ba-bfaa-36915107d59e}
213
                UserHelper userHelper = UserHelperAccess.userHelper().withCache(getCache());
214
                Set<RegistrationStatus> availableStatus = new HashSet<>();
215

    
216
                boolean canChangeStatus = userHelper.userHasPermission(regDto.registration(), CRUD.UPDATE);
217
                availableStatus.add(regDto.getStatus());
218
                if(canChangeStatus){
219
                    if(userHelper.userIsAdmin()){
220
                        availableStatus.addAll(Arrays.asList(RegistrationStatus.values()));
221
                    } else {
222
                        availableStatus.addAll(RegistrationStatusTransitions.possibleTransitions(regDto.getStatus()));
223
                    }
224
                }
225

    
226
                RegistrationStatusSelect select = new RegistrationStatusSelect(null, selectFieldFactory.buildBeanItemContainer(
227
                        RegistrationStatus.class,
228
                        availableStatus.toArray(new RegistrationStatus[availableStatus.size()]))
229
                        );
230
                select.setValue(regDto.getStatus());
231
                select.addValueChangeListener(e -> saveRegistrationStatusChange(regDto.getUuid(), e.getProperty().getValue()));
232
                select.setEnabled(canChangeStatus);
233
                select.setNullSelectionAllowed(false);
234
                return select;
235
            }
236

    
237

    
238
        });
239
        loadWorkingSet(getView().getCitationUuid());
240
        applyWorkingset();
241

    
242
    }
243

    
244
    private void applyWorkingset(){
245
         getView().setWorkingset(workingset);
246
        // PagingProviders and CacheGenerator for the existingNameCombobox
247
        activateComboboxes();
248
    }
249

    
250
    protected void activateComboboxes() {
251
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenerator = new CdmTitleCacheCaptionGenerator<TaxonName>();
252
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenerator);
253
        CdmFilterablePagingProvider<TaxonName, TaxonName> pagingProvider = pagingProviderFactory.taxonNamesWithoutOrthophicIncorrect();
254
        getView().getAddExistingNameCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
255
    }
256

    
257
    /**
258
     * @param referenceID
259
     */
260
    protected void loadWorkingSet(UUID referenceUuid) {
261

    
262
        try {
263
            workingset = getWorkingSetService().loadWorkingSetByReferenceUuid(referenceUuid, true);
264
        } catch (RegistrationValidationException error) {
265
            logger.error(error);
266
            showErrorDialog("Validation Error", error.getMessage());
267
        } catch(PermissionDeniedException e){
268
            logger.info(e);
269
            ((AccessRestrictedView)getView()).setAccessDeniedMessage(e.getMessage());
270
        }
271
        cache = new CdmTransientEntityAndUuidCacher(this);
272
        for(Registration registration : workingset.getRegistrations()) {
273
            addRootEntity(registration);
274
        }
275
    }
276

    
277
    /**
278
     * @param errorDialogCaption
279
     * @param errorMessage
280
     */
281
    public void showErrorDialog(String errorDialogCaption, String errorMessage) {
282
        Window errorDialog = new Window(errorDialogCaption);
283
        errorDialog.setModal(true);
284
        VerticalLayout subContent = new VerticalLayout();
285
        subContent.setMargin(true);
286
        errorDialog.setContent(subContent);
287
        subContent.addComponent(new Label(errorMessage));
288
        UI.getCurrent().addWindow(errorDialog);
289
    }
290

    
291
    private void saveRegistrationStatusChange(UUID uuid, Object value) {
292
        Registration reg = getRepo().getRegistrationService().load(uuid);
293
        if(reg == null){
294
            // registration was not yet persisted, ignore
295
            return;
296
        }
297
        if(value != null && value instanceof RegistrationStatus){
298
            if(!Objects.equals(value, reg.getStatus())){
299
                reg.updateStatusAndDate((RegistrationStatus)value);
300
                cdmStore.saveBean(reg, (AbstractView)getView());
301
                refreshView(true);
302
            }
303
        } else {
304
            // only log here as error
305
            logger.error("Ivalid attempt to set RegistrationStatus to " + Objects.toString(value.toString(), "NULL"));
306
        }
307
    }
308

    
309

    
310
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
311
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
312

    
313
        if(!checkFromOwnView(event)){
314
            return;
315
        }
316

    
317
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
318
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
319
        popup.loadInEditor(null);
320
    }
321

    
322
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
323
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
324

    
325
        if(!checkFromOwnView(event)){
326
            return;
327
        }
328
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
329
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
330
        popup.withDeleteButton(true);
331
        popup.loadInEditor(event.getEntityUuid());
332
    }
333

    
334
    @EventBusListenerMethod
335
    public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
336
        if(event.getPopup() instanceof ReferencePopupEditor){
337
            if(event.getReason().equals(Reason.SAVE)){
338
                refreshView(true);
339
            }
340
        }
341
    }
342

    
343
    @EventBusListenerMethod
344
    public void onDoneWithSpecimenTypeDesignationWorkingsetPopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
345
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
346
            if(event.getReason().equals(Reason.SAVE)){
347
                refreshView(true);
348
            }
349
        }
350
    }
351

    
352
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
353
    public void onRegistrationEditorAction(RegistrationEditorAction event) {
354

    
355
        if(!checkFromOwnView(event)){
356
            return;
357
        }
358

    
359
        RegistrationPopupEditor popup = openPopupEditor(RegistrationPopupEditor.class, event);
360
        popup.loadInEditor(event.getEntityUuid());
361
    }
362

    
363
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
364
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
365

    
366
        if(!checkFromOwnView(event)){
367
            return;
368
        }
369

    
370
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
371
        popup.setParentEditorActionContext(event.getContext(), event.getTarget());
372
        popup.withDeleteButton(true);
373
        TaxonNamePopupEditorConfig.configureForNomenclaturalAct(popup);
374
        popup.loadInEditor(event.getEntityUuid());
375
        if(event.hasSource() && event.getSource().isReadOnly()){
376
            // avoid resetting readonly to false
377
            popup.setReadOnly(true);
378
        }
379

    
380
    }
381

    
382

    
383
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
384
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
385

    
386
        if(!checkFromOwnView(event)){
387
            return;
388
        }
389

    
390
        getView().getAddNewNameRegistrationButton().setEnabled(false);
391
        if(newNameForRegistrationPopupEditor == null){
392
            TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
393
            newNameForRegistrationPopupEditor = popup;
394
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
395
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE,CRUD.DELETE));
396
            popup.withDeleteButton(true);
397
            popup.setCdmEntityInstantiator(new BeanInstantiator<TaxonName>() {
398

    
399
                @Override
400
                public TaxonName createNewBean() {
401
                    TaxonName newTaxonName = TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
402
                    newTaxonName.setNomenclaturalReference(getRepo().getReferenceService().load(workingset.getCitationUuid(), TaxonNameEditorPresenter.REFERENCE_INIT_STRATEGY ));
403
                    return newTaxonName;
404
                }
405
            });
406
            TaxonNamePopupEditorConfig.configureForNomenclaturalAct(popup);
407
            popup.loadInEditor(null);
408
        }
409
    }
410

    
411
    /**
412
     * Creates a new <code>Registration</code> for a new name that has just been edited
413
     * using a <code>TaxonNamePopupEditor</code>. The popup editor which has been opened to
414
     * edit the new name was remembered in <code>newNameForRegistrationPopupEditor</code>.
415
     * Any blocking registrations which have been created while editing the new name are
416
     * temporarily stored in <code>newNameBlockingRegistrations</code> until the registration
417
     * for the first name has been created. Additional new names are created for example
418
     * when a new name as basionym, replaced synonym, etc to the new name is created.
419
     * <p>
420
     * See also {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)}).
421
     *
422
     * @param event
423
     * @throws RegistrationValidationException
424
     */
425
    @EventBusListenerMethod
426
    public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
427
        if(event.getPopup() instanceof TaxonNamePopupEditor){
428
            if(newNameForRegistrationPopupEditor != null && event.getPopup().equals(newNameForRegistrationPopupEditor)){
429
                if(event.getReason().equals(Reason.SAVE)){
430
                    try {
431
                        TaxonName taxonName = newNameForRegistrationPopupEditor.getBean().cdmEntity();
432
                        registrationWorkflowService.createRegistration(taxonName, newNameBlockingRegistrations);
433
                        loadWorkingSet(workingset.getCitationUuid());
434
                        refreshView(true);
435
                        getView().getAddNewNameRegistrationButton().setEnabled(true);
436
                    } finally {
437
                        clearSession();
438
                        refreshView(true);
439
                        getView().getAddNewNameRegistrationButton().setEnabled(true);
440
                    }
441
                }
442
                // nullify and clear the memory on this popup editor in any case (SAVE, CANCEL, DELETE)
443
                newNameForRegistrationPopupEditor = null;
444
                newNameBlockingRegistrations.clear();
445
                getView().getAddNewNameRegistrationButton().setEnabled(true);
446
            } else {
447
                refreshView(true);
448
            }
449
        }
450
    }
451

    
452

    
453

    
454

    
455
    /**
456
     * Creates a new Registration for an exiting (previously published) name.
457
     *
458
     * @param event
459
     * @throws RegistrationValidationException
460
     */
461
    @EventBusListenerMethod
462
    public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event) throws RegistrationValidationException {
463

    
464
        if(!event.isStart()){
465
            return;
466
        }
467

    
468
        getView().getAddExistingNameCombobox().commit(); // update the chosen value in the datasource
469
        TaxonName typifiedName = getView().getAddExistingNameCombobox().getValue();
470
        if(typifiedName != null){
471
            boolean doReloadWorkingSet = false;
472
            try {
473
                doReloadWorkingSet = registrationWorkflowService.createRegistrationforExistingName(workingset, typifiedName);
474
            } finally {
475
                clearSession();
476
                refreshView(doReloadWorkingSet);
477
                getView().getAddExistingNameRegistrationButton().setEnabled(false);
478
            }
479
        } else {
480
            logger.error("Seletced name is NULL");
481
        }
482

    
483
    }
484

    
485
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
486
    public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event) {
487

    
488
        if(!checkFromOwnView(event)){
489
            return;
490
        }
491

    
492
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET ){
493
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
494
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
495
            popup.withDeleteButton(true);
496
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
497
            if(event.hasSource()){
498
                // propagate readonly state from source button to popup
499
                popup.setReadOnly(event.getSource().isReadOnly());
500
            }
501
        } else {
502
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
503
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
504
            popup.withDeleteButton(true);
505
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
506

    
507
            popup.getCitationCombobox().setEnabled(false);
508
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
509

    
510
            if(event.hasSource()){
511
                // propagate readonly state from source button to popup
512
                popup.setReadOnly(event.getSource().isReadOnly());
513
            }
514
            nameTypeDesignationPopupEditorRegistrationUUIDMap.put(popup, event.getRegistrationUuid());
515
        }
516
    }
517

    
518
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
519
    public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event) {
520

    
521
        if(!event.hasSource()){
522
            return;
523
        }
524

    
525
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET){
526
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
527
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
528
            TypeDesignationWorkingsetEditorIdSet identifierSet;
529
            UUID typifiedNameUuid;
530

    
531
            RegistrationDTO registrationDTO = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
532
            EntityReference typifiedNameRef = registrationDTO.getTypifiedNameRef();
533
            if(typifiedNameRef != null){
534
                // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
535
                typifiedNameUuid = typifiedNameRef.getUuid();
536
            } else {
537
                // case of registrations with a name in the nomenclatural act.
538
                typifiedNameUuid = registrationDTO.getNameRef().getUuid();
539
            }
540

    
541
            identifierSet = new TypeDesignationWorkingsetEditorIdSet(
542
                    event.getRegistrationUuid(),
543
                    getView().getCitationUuid(),
544
                    typifiedNameUuid
545
                    );
546
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
547
            popup.loadInEditor(identifierSet);
548
            popup.withDeleteButton(true);
549
            if(event.hasSource()){
550
                // propagate readonly state from source component to popup
551
                popup.setReadOnly(event.getSource().isReadOnly());
552
            }
553
        } else {
554
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
555
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
556
            popup.withDeleteButton(true);
557
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
558
            RegistrationDTO regDto = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
559
            Reference citation = regDto.getCitation();
560
            nameTypeDesignationPopupEditorRegistrationUUIDMap.put(popup, event.getRegistrationUuid());
561
            popup.setBeanInstantiator(new BeanInstantiator<NameTypeDesignation>() {
562

    
563
                @Override
564
                public NameTypeDesignation createNewBean() {
565

    
566
                    TaxonName typifiedName = getRepo().getNameService().load(event.getTypifiedNameUuid(), Arrays.asList(new String[]{"typeDesignations", "homotypicalGroup"}));
567
                    NameTypeDesignation nameTypeDesignation  = NameTypeDesignation.NewInstance();
568
                    nameTypeDesignation.setCitation(citation);
569
                    nameTypeDesignation.getTypifiedNames().add(typifiedName);
570
                    return nameTypeDesignation;
571
                }
572
            });
573
            popup.loadInEditor(null);
574
            popup.getCitationCombobox().setEnabled(false);
575
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
576
            if(event.hasSource()){
577
                // propagate readonly state from source component to popup
578
                popup.setReadOnly(event.getSource().isReadOnly());
579
            }
580
        }
581
    }
582

    
583
    /**
584
     * Performs final actions after a TypeDesignationEditor which has been
585
     * opened to add a TypeDesignation to a Registration object which was
586
     * created for an previously published name. Prior adding a typedesignation,
587
     * the according Registration object is dangling, that has no association to
588
     * any entity denoting an nomenclatural act which has a reference to a
589
     * publication. This means that the registration object is not in the
590
     * working set.
591
     *
592
     *
593
     * @param event
594
     * @throws RegistrationValidationException
595
     */
596
    @EventBusListenerMethod
597
    public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event) {
598
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
599
            if(event.getReason().equals(Reason.SAVE)){
600
                // NOTE: adding the SpecimenTypeDesignations to the registration is done in the
601
                // SpecimenTypeDesignationWorkingSetServiceImpl.save(SpecimenTypeDesignationWorkingSetDTO dto) method
602
                refreshView(true);
603
            } else if(event.getReason().equals(Reason.CANCEL)){
604
                // noting to do
605
            }
606
        } else if(event.getPopup() instanceof NameTypeDesignationPopupEditor){
607
            if(event.getReason().equals(Reason.SAVE)){
608
                UUID typeDesignationUuid = ((NameTypeDesignationPopupEditor)event.getPopup()).getBean().getUuid();
609

    
610
                try {
611
                    clearSession();
612
                    Stack<EditorActionContext>context = ((AbstractPopupEditor)event.getPopup()).getEditorActionContext();
613
                    Registration registration = findRegistrationInContext(context);
614
                    getRepo().getSession().clear();
615
                    registrationWorkflowService.addTypeDesignation(typeDesignationUuid, registration);
616
                    nameTypeDesignationPopupEditorRegistrationUUIDMap.remove(event.getPopup());
617
                } finally {
618
                    clearSession();
619
                    refreshView(true);
620
                }
621
            } else if(event.getReason().equals(Reason.CANCEL)){
622
                // noting to do
623
            }
624

    
625
        }
626
        // ignore other editors
627
    }
628

    
629
    /**
630
     *
631
     */
632
    public void clearSession() {
633
        getRepo().clearSession();
634
    }
635

    
636

    
637
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationWorkingSet.class)
638
    public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent<RegistrationWorkingSet,?> event) {
639

    
640
        if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
641
            List<String> messages = new ArrayList<>();
642
            for(RegistrationDTO dto : workingset.getRegistrationDTOs()){
643
                dto.getValidationProblems().forEach(m -> messages.add(dto.getSummary() + ": " + m));
644
            }
645
            getView().openDetailsPopup("Validation Problems", messages);
646
        }
647
    }
648

    
649
    @EventBusListenerMethod
650
    public void onEntityChangeEvent(EntityChangeEvent event){
651

    
652
        if(workingset == null){
653
            return;
654
        }
655
        if(Reference.class.isAssignableFrom(event.getEntityType())){
656

    
657
            if(workingset.getCitationUuid().equals(event.getEntityUuid())){
658
                if(event.isRemovedType()){
659
                    viewEventBus.publish(EventScope.UI, this, new NavigationEvent(StartRegistrationViewBean.NAME));
660
                } else {
661
                    refreshView(true);
662
                }
663
            }
664

    
665
        } else
666
        if(Registration.class.isAssignableFrom(event.getEntityType())){
667
            if(workingset.getRegistrations().stream().anyMatch(reg -> reg.getUuid() == event.getEntityUuid())){
668
                refreshView(true);
669
            }
670
        } else
671
        if(TaxonName.class.isAssignableFrom(event.getEntityType())){
672
            if(event.getType().equals(EntityChangeEvent.Type.CREATED)){
673
                Stack<EditorActionContext>context = ((AbstractPopupEditor)event.getSourceView()).getEditorActionContext();
674
                EditorActionContext rootContext = context.get(0);
675
                if(rootContext.getParentView().equals(getView()) && event.getSourceView() != newNameForRegistrationPopupEditor){
676
                    try {
677
                        clearSession();
678
                        // create a blocking registration, the new Registration will be persisted
679
                        UUID taxonNameUUID = event.getEntityUuid();
680

    
681
                        if(context.get(1).getParentView() instanceof TaxonNamePopupEditor && !((TaxonNamePopupEditor)context.get(1).getParentView()).getBean().cdmEntity().isPersited()){
682
                            // Oha!! The event came from a popup editor and the
683
                            // first popup in the context is a TaxonNameEditor with un-persisted name
684
                            // This is a name for a new registration which has not yet been created.
685
                            // It is necessary to store blocking registrations in the newNameBlockingRegistrations
686
                            Registration blockingRegistration = getRepo().getRegistrationService().createRegistrationForName(taxonNameUUID);
687
                            newNameBlockingRegistrations.add(blockingRegistration);
688
                            logger.debug("Blocking registration created and memorized");
689
                        } else {
690
                            Registration registration = findRegistrationInContext(context);
691
                            // some new name somehow related to an existing registration
692
                            registrationWorkflowService.addBlockingRegistration(taxonNameUUID, registration);
693
                        }
694
                    } finally {
695
                        clearSession();
696
                    }
697

    
698
                } else {
699
                    // in case of creating a new name for a registration the parent view is the TaxonNamePopupEditor
700
                    // this is set
701
                    logger.debug("Non blocking registration, since a new name for a new registration has been created");
702
                }
703
            }
704
            if(workingset.getRegistrationDTOs().stream().anyMatch(reg ->
705
                reg.getTypifiedNameRef() != null
706
                && reg.getTypifiedNameRef().getUuid().equals(event.getEntityUuid()))){
707
                    refreshView(true);
708
            }
709
        } else
710
        if(TypeDesignationBase.class.isAssignableFrom(event.getEntityType())){
711
            if(workingset.getRegistrationDTOs().stream().anyMatch(
712
                    reg -> reg.typeDesignations() != null && reg.typeDesignations().stream().anyMatch(
713
                            td -> td.getUuid() == event.getEntityUuid()
714
                            )
715
                        )
716
                    ){
717
                refreshView(true);
718
            }
719
        }
720
    }
721

    
722
    /**
723
     * Finds the Registration in the EditorContext stack
724
     *
725
     * @param context
726
     * @return
727
     */
728
    public Registration findRegistrationInContext(Stack<EditorActionContext> context) {
729
        EditorActionContext rootCtx = context.get(0);
730
        TypedEntityReference<Registration> regReference = (TypedEntityReference<Registration>)rootCtx.getParentEntity();
731
        Optional<RegistrationDTO> registrationDTOOptional = workingset.getRegistrationDTO(regReference.getUuid());
732
        if(!registrationDTOOptional.isPresent()){
733
            logger.error("RegistrationDTO missing in rootCtx.");
734
        }
735
        Registration registration = registrationDTOOptional.get().registration();
736

    
737
        // registration = reloadRegistration(registration);
738
        return registration;
739
    }
740

    
741

    
742

    
743
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationDTO.class)
744
    public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent<RegistrationDTO, UUID> event) {
745

    
746
        // FIXME check from own view!!!
747
        if(getView() == null){
748
            return;
749
        }
750

    
751
        UUID registrationUuid = event.getIdentifier();
752

    
753
        RegistrationDTO regDto = workingset.getRegistrationDTO(registrationUuid).get();
754
        if(event.getProperty().equals(RegistrationItem.BLOCKED_BY)){
755

    
756
            Set<RegistrationDTO> blockingRegs;
757
            if(regDto.registration().isPersited()){
758
                blockingRegs = getWorkingSetService().loadBlockingRegistrations(registrationUuid);
759
            } else {
760
                blockingRegs = new HashSet<RegistrationDTO>(getWorkingSetService().makeDTOs(regDto.registration().getBlockedBy()));
761
            }
762
            getView().setBlockingRegistrations(registrationUuid, blockingRegs);
763
        } else if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
764
            getView().openDetailsPopup("Validation Problems", regDto.getValidationProblems());
765
        }
766
    }
767

    
768
    /**
769
     * {@inheritDoc}
770
     */
771
    @Override
772
    public ICdmEntityUuidCacher getCache() {
773
        return cache;
774
    }
775

    
776
    /**
777
     * {@inheritDoc}
778
     */
779
    @Override
780
    public void addRootEntity(CdmBase entity) {
781
        rootEntities.add(entity);
782
        cache.load(entity);
783
    }
784

    
785

    
786
    /**
787
     * {@inheritDoc}
788
     */
789
    @Override
790
    public Collection<CdmBase> getRootEntities() {
791
        return rootEntities;
792
    }
793

    
794
    @Override
795
    public void destroy() throws Exception {
796
        super.destroy();
797
        disposeCache();
798
    }
799

    
800
    /**
801
     * {@inheritDoc}
802
     */
803
    @Override
804
    public void disposeCache() {
805
        cache.dispose();
806
    }
807

    
808
    /**
809
     * @param name
810
     * @return
811
     */
812
    public boolean canCreateNameRegistrationFor(TaxonName name) {
813
        return registrationWorkflowService.canCreateNameRegistrationFor(workingset, name);
814
    }
815

    
816
    /**
817
     * @param name
818
     * @return
819
     */
820
    public boolean checkWokingsetContainsProtologe(TaxonName name) {
821
        return registrationWorkflowService.checkWokingsetContainsProtologe(workingset, name);
822
    }
823

    
824
}
(10-10/18)