Project

General

Profile

Download (36.6 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.Set;
21
import java.util.Stack;
22
import java.util.UUID;
23

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

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

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

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

    
109
    private static final Logger logger = Logger.getLogger(RegistrationWorkingsetPresenter.class);
110

    
111
    private static final long serialVersionUID = 1L;
112

    
113
    @Autowired
114
    private IRegistrationWorkingSetService regWorkingSetService;
115

    
116
    @Autowired
117
    private IRegistrationWorkflowService registrationWorkflowService;
118

    
119
    @Autowired
120
    private CdmFilterablePagingProviderFactory pagingProviderFactory;
121

    
122
    @Autowired
123
    private CdmBeanItemContainerFactory selectFieldFactory;
124

    
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
     * Always create a new Store
165
     *
166
     * @return
167
     */
168
    protected CdmStore<Registration, IRegistrationService> getRegistrationStore(){
169
        return new CdmStore<Registration, IRegistrationService>(getRepo(), getRepo().getRegistrationService());
170
    }
171

    
172
    /**
173
     * Always create a new Store
174
     *
175
     * @return
176
     */
177
    protected CdmStore<TaxonName, INameService> getTaxonNameStore(){
178
        return new  CdmStore<TaxonName, INameService>(getRepo(), getRepo().getNameService());
179
    }
180

    
181

    
182

    
183
    /**
184
     * @param doReload reload the workingset from the persistent storage.
185
     *  Workingsets which are not yet persisted are preserved.
186
     *
187
     */
188
    protected void refreshView(boolean doReload) {
189
        if(workingset == null){
190
            return; // nothing to do
191
        }
192
        if(doReload){
193
            List<RegistrationDTO> unpersisted = new ArrayList<>();
194
            for(RegistrationDTO regDto : workingset.getRegistrationDTOs()){
195
                if(!regDto.registration().isPersited()){
196
                    unpersisted.add(regDto);
197
                }
198
            }
199
            loadWorkingSet(workingset.getCitationUuid());
200
            for(RegistrationDTO regDtoUnpersisted : unpersisted){
201
                if(!workingset.getRegistrationDTOs().stream().anyMatch(dto -> dto.getUuid().equals(regDtoUnpersisted.getUuid()))){
202
                    // only add if the regDtoUnpersisted has not been persisted meanwhile
203
                    try {
204
                        workingset.add(regDtoUnpersisted);
205
                    } catch (RegistrationValidationException e) {
206
                        // would never happen here //
207
                    }
208
                }
209
            }
210
        }
211
        applyWorkingset();
212
    }
213

    
214
    /**
215
     * {@inheritDoc}
216
     */
217
    @Override
218
    public void handleViewEntered() {
219
        super.handleViewEntered();
220
        // TODO currently cannot specify type more precisely, see AbstractSelect
221
        // FIXME externalize into class file!!!!!!!!!!!!
222
        getView().setStatusComponentInstantiator(new RegistrationStatusFieldInstantiator<Object>(){
223

    
224
            private static final long serialVersionUID = 7099181280977511048L;
225

    
226
            @Override
227
            public AbstractField<Object> create(RegistrationDTO regDto) {
228

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

    
233
                boolean canChangeStatus = userHelper.userHasPermission(regDto.registration(), CRUD.UPDATE);
234
                availableStatus.add(regDto.getStatus());
235
                if(canChangeStatus){
236
                    if(userHelper.userIsAdmin()){
237
                        availableStatus.addAll(Arrays.asList(RegistrationStatus.values()));
238
                    } else {
239
                        availableStatus.addAll(RegistrationStatusTransitions.possibleTransitions(regDto.getStatus()));
240
                    }
241
                }
242

    
243
                RegistrationStatusSelect select = new RegistrationStatusSelect(null, selectFieldFactory.buildBeanItemContainer(
244
                        RegistrationStatus.class,
245
                        availableStatus.toArray(new RegistrationStatus[availableStatus.size()]))
246
                        );
247
                select.setValue(regDto.getStatus());
248
                select.addValueChangeListener(e -> saveRegistrationStatusChange(regDto.getUuid(), e.getProperty().getValue()));
249
                select.setEnabled(canChangeStatus);
250
                select.setNullSelectionAllowed(false);
251
                return select;
252
            }
253

    
254

    
255
        });
256
        loadWorkingSet(getView().getCitationUuid());
257
        applyWorkingset();
258

    
259
    }
260

    
261
    private void applyWorkingset(){
262
         getView().setWorkingset(workingset);
263
        // PagingProviders and CacheGenerator for the existingNameCombobox
264
        activateComboboxes();
265
    }
266

    
267
    protected void activateComboboxes() {
268
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenerator = new CdmTitleCacheCaptionGenerator<TaxonName>();
269
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenerator);
270
        CdmFilterablePagingProvider<TaxonName, TaxonName> pagingProvider = pagingProviderFactory.taxonNamesWithoutOrthophicIncorrect();
271
        getView().getAddExistingNameCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
272
    }
273

    
274
    /**
275
     * @param referenceID
276
     */
277
    protected void loadWorkingSet(UUID referenceUuid) {
278

    
279
        try {
280
            workingset = getWorkingSetService().loadWorkingSetByReferenceUuid(referenceUuid, true);
281
        } catch (RegistrationValidationException error) {
282
            logger.error(error);
283
            showErrorDialog("Validation Error", error.getMessage());
284
        } catch(PermissionDeniedException e){
285
            logger.info(e);
286
            ((AccessRestrictedView)getView()).setAccessDeniedMessage(e.getMessage());
287
        }
288
        cache = new CdmTransientEntityAndUuidCacher(this);
289
        for(Registration registration : workingset.getRegistrations()) {
290
            addRootEntity(registration);
291
        }
292
    }
293

    
294
    /**
295
     * @param errorDialogCaption
296
     * @param errorMessage
297
     */
298
    public void showErrorDialog(String errorDialogCaption, String errorMessage) {
299
        Window errorDialog = new Window(errorDialogCaption);
300
        errorDialog.setModal(true);
301
        VerticalLayout subContent = new VerticalLayout();
302
        subContent.setMargin(true);
303
        errorDialog.setContent(subContent);
304
        subContent.addComponent(new Label(errorMessage));
305
        UI.getCurrent().addWindow(errorDialog);
306
    }
307

    
308
    private void saveRegistrationStatusChange(UUID uuid, Object value) {
309
        Registration reg = getRepo().getRegistrationService().load(uuid);
310
        if(reg == null){
311
            // registration was not yet persisted, ignore
312
            return;
313
        }
314
        if(value != null && value instanceof RegistrationStatus){
315
            if(!Objects.equals(value, reg.getStatus())){
316
                reg.updateStatusAndDate((RegistrationStatus)value);
317
                getRegistrationStore().saveBean(reg, (AbstractView)getView());
318
                refreshView(true);
319
            }
320
        } else {
321
            // only log here as error
322
            logger.error("Ivalid attempt to set RegistrationStatus to " + Objects.toString(value.toString(), "NULL"));
323
        }
324
    }
325

    
326

    
327
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
328
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
329

    
330
        if(!checkFromOwnView(event)){
331
            return;
332
        }
333

    
334
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
335
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
336
        popup.loadInEditor(null);
337
    }
338

    
339
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
340
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
341

    
342
        if(!checkFromOwnView(event)){
343
            return;
344
        }
345
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
346
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
347
        popup.withDeleteButton(true);
348
        popup.loadInEditor(event.getEntityUuid());
349
    }
350

    
351
    @EventBusListenerMethod
352
    public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
353
        if(event.getPopup() instanceof ReferencePopupEditor){
354
            if(event.getReason().equals(Reason.SAVE)){
355
                refreshView(true);
356
            }
357
        }
358
    }
359

    
360
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
361
    public void onRegistrationEditorAction(RegistrationEditorAction event) {
362

    
363
        if(!checkFromOwnView(event)){
364
            return;
365
        }
366

    
367
        RegistrationPopupEditor popup = openPopupEditor(RegistrationPopupEditor.class, event);
368
        popup.loadInEditor(event.getEntityUuid());
369
    }
370

    
371
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
372
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
373

    
374
        if(!checkFromOwnView(event)){
375
            return;
376
        }
377

    
378
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
379
        popup.setParentEditorActionContext(event.getContext(), event.getTarget());
380
        popup.withDeleteButton(true);
381
        TaxonNamePopupEditorConfig.configureForNomenclaturalAct(popup);
382
        popup.loadInEditor(event.getEntityUuid());
383
        if(event.hasSource() && event.getSource().isReadOnly()){
384
            // avoid resetting readonly to false
385
            popup.setReadOnly(true);
386
        }
387

    
388
    }
389

    
390

    
391
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
392
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
393

    
394
        if(!checkFromOwnView(event)){
395
            return;
396
        }
397

    
398
        getView().getAddNewNameRegistrationButton().setEnabled(false);
399
        if(newNameForRegistrationPopupEditor == null){
400
            TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
401
            newNameForRegistrationPopupEditor = popup;
402
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
403
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE,CRUD.DELETE));
404
            popup.withDeleteButton(true);
405
            popup.setCdmEntityInstantiator(new BeanInstantiator<TaxonName>() {
406

    
407
                @Override
408
                public TaxonName createNewBean() {
409
                    TaxonName newTaxonName = TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
410
                    newTaxonName.setNomenclaturalReference(getRepo().getReferenceService().load(workingset.getCitationUuid(), TaxonNameEditorPresenter.REFERENCE_INIT_STRATEGY ));
411
                    return newTaxonName;
412
                }
413
            });
414
            TaxonNamePopupEditorConfig.configureForNomenclaturalAct(popup);
415
            popup.loadInEditor(null);
416
        }
417
    }
418

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

    
456
            if(registration == null){
457
                // no new registration has been created above, so there must be an existing one.
458
                registration = findRegistrationInContext(event.getPopup());
459
            }
460

    
461
            // Check if the other names used in the context of the name are registered yet.
462
            TaxonNamePopupEditor nameEditor = (TaxonNamePopupEditor)event.getPopup();
463
            Set<TaxonName> namesToCheck = new HashSet<>();
464

    
465
            namesToCheck.addAll(nameEditor.getBasionymComboboxSelect().getValue());
466
            namesToCheck.addAll(nameEditor.getReplacedSynonymsComboboxSelect().getValue());
467
            namesToCheck.add(nameEditor.getValidationField().getRelatedNameComboBox().getValue());
468
            namesToCheck.add(nameEditor.getOrthographicVariantField().getRelatedNameComboBox().getValue());
469

    
470
            for(TaxonName name : namesToCheck){
471
                if(name != null){
472
                    doRefreshView |= registrationWorkflowService.addBlockingRegistration(name.getUuid(), registration) != null;
473
                }
474
            }
475

    
476
            refreshView(doRefreshView);
477
        }
478
    }
479

    
480

    
481

    
482

    
483
    /**
484
     * Creates a new Registration for an exiting (previously published) name.
485
     *
486
     * @param event
487
     * @throws RegistrationValidationException
488
     */
489
    @EventBusListenerMethod
490
    public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event) throws RegistrationValidationException {
491

    
492
        if(!event.isStart()){
493
            return;
494
        }
495

    
496
        getView().getAddExistingNameCombobox().commit(); // update the chosen value in the datasource
497
        TaxonName typifiedName = getView().getAddExistingNameCombobox().getValue();
498
        if(typifiedName != null){
499
            boolean doReloadWorkingSet = false;
500
            try {
501
                doReloadWorkingSet = registrationWorkflowService.createRegistrationforExistingName(workingset, typifiedName);
502
            } finally {
503
                getRepo().getSession().clear(); // #7702;
504
                refreshView(doReloadWorkingSet);
505
                getView().getAddExistingNameRegistrationButton().setEnabled(false);
506
            }
507
        } else {
508
            logger.error("Seletced name is NULL");
509
        }
510

    
511
    }
512

    
513
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
514
    public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event) {
515

    
516
        if(!checkFromOwnView(event)){
517
            return;
518
        }
519

    
520
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET ){
521
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
522
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
523
            popup.withDeleteButton(true);
524
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
525
            if(event.hasSource()){
526
                // propagate readonly state from source button to popup
527
                popup.setReadOnly(event.getSource().isReadOnly());
528
            }
529
        } else {
530
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
531
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
532
            popup.withDeleteButton(true);
533
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
534

    
535
            popup.getCitationCombobox().setEnabled(false);
536
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
537

    
538
            if(event.hasSource()){
539
                // propagate readonly state from source button to popup
540
                popup.setReadOnly(event.getSource().isReadOnly());
541
            }
542
            nameTypeDesignationPopupEditorRegistrationUUIDMap.put(popup, event.getRegistrationUuid());
543
        }
544
    }
545

    
546
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
547
    public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event) {
548

    
549
        if(!event.hasSource()){
550
            return;
551
        }
552

    
553
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET){
554
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
555
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
556
            TypeDesignationWorkingsetEditorIdSet identifierSet;
557
            UUID typifiedNameUuid;
558

    
559
            RegistrationDTO registrationDTO = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
560
            EntityReference typifiedNameRef = registrationDTO.getTypifiedNameRef();
561
            if(typifiedNameRef != null){
562
                // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
563
                typifiedNameUuid = typifiedNameRef.getUuid();
564
            } else {
565
                // case of registrations with a name in the nomenclatural act.
566
                typifiedNameUuid = registrationDTO.getNameRef().getUuid();
567
            }
568

    
569
            identifierSet = new TypeDesignationWorkingsetEditorIdSet(
570
                    event.getRegistrationUuid(),
571
                    getView().getCitationUuid(),
572
                    typifiedNameUuid
573
                    );
574
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
575
            popup.loadInEditor(identifierSet);
576
            popup.withDeleteButton(true);
577
            if(event.hasSource()){
578
                // propagate readonly state from source component to popup
579
                popup.setReadOnly(event.getSource().isReadOnly());
580
            }
581
        } else {
582
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
583
            popup.setParentEditorActionContext(event.getContext(), event.getTarget());
584
            popup.withDeleteButton(true);
585
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
586
            RegistrationDTO regDto = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
587
            Reference citation = regDto.getCitation();
588
            nameTypeDesignationPopupEditorRegistrationUUIDMap.put(popup, event.getRegistrationUuid());
589
            popup.setBeanInstantiator(new BeanInstantiator<NameTypeDesignation>() {
590

    
591
                @Override
592
                public NameTypeDesignation createNewBean() {
593

    
594
                    TaxonName typifiedName = getRepo().getNameService().load(event.getTypifiedNameUuid(), Arrays.asList(new String[]{"typeDesignations", "homotypicalGroup"}));
595
                    NameTypeDesignation nameTypeDesignation  = NameTypeDesignation.NewInstance();
596
                    nameTypeDesignation.setCitation(citation);
597
                    nameTypeDesignation.getTypifiedNames().add(typifiedName);
598
                    return nameTypeDesignation;
599
                }
600
            });
601
            popup.loadInEditor(null);
602
            popup.getCitationCombobox().setEnabled(false);
603
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
604
            if(event.hasSource()){
605
                // propagate readonly state from source component to popup
606
                popup.setReadOnly(event.getSource().isReadOnly());
607
            }
608
        }
609
    }
610

    
611
    /**
612
     * Performs final actions after a TypeDesignationEditor which has been
613
     * opened to add a TypeDesignation to a Registration object which was
614
     * created for an previously published name. Prior adding a typedesignation,
615
     * the according Registration object is dangling, that has no association to
616
     * any entity denoting an nomenclatural act which has a reference to a
617
     * publication. This means that the registration object is not in the
618
     * working set.
619
     *
620
     *
621
     * @param event
622
     * @throws RegistrationValidationException
623
     */
624
    @EventBusListenerMethod
625
    public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event) {
626
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
627
            if(event.getReason().equals(Reason.SAVE)){
628
                // NOTE: adding the SpecimenTypeDesignations to the registration is done in the
629
                // SpecimenTypeDesignationWorkingSetServiceImpl.save(SpecimenTypeDesignationWorkingSetDTO dto) method
630
                refreshView(true);
631
            } else if(event.getReason().equals(Reason.CANCEL)){
632
                // noting to do
633
            }
634
        } else if(event.getPopup() instanceof NameTypeDesignationPopupEditor){
635
            if(event.getReason().equals(Reason.SAVE)){
636

    
637
                Registration registration = null;
638
                boolean doRefreshView = false;
639

    
640
                UUID typeDesignationUuid = ((NameTypeDesignationPopupEditor)event.getPopup()).getBean().getUuid();
641

    
642
                try {
643
                    registration = findRegistrationInContext(event.getPopup());
644
                    getRepo().getSession().clear();
645
                    registrationWorkflowService.addTypeDesignation(typeDesignationUuid, registration);
646
                    nameTypeDesignationPopupEditorRegistrationUUIDMap.remove(event.getPopup());
647
                } finally {
648
                    getRepo().getSession().clear();
649
                    doRefreshView = true;
650
                }
651

    
652
                if(registration == null){
653
                    // no new registration has been created above, so there must be an existing one.
654
                    registration = findRegistrationInContext(event.getPopup());
655
                }
656

    
657
                // Check if the other names used in the context of the name are registered yet.
658
                NameTypeDesignationPopupEditor nameEditor = (NameTypeDesignationPopupEditor)event.getPopup();
659
                Set<TaxonName> namesToCheck = new HashSet<>();
660

    
661
                namesToCheck.add(nameEditor.getTypeNameField().getValue());
662

    
663
                for(TaxonName name : namesToCheck){
664
                    if(name != null){
665
                        doRefreshView |= registrationWorkflowService.addBlockingRegistration(name.getUuid(), registration) != null;
666
                    }
667

    
668
                }
669

    
670
                refreshView(doRefreshView);
671

    
672
            } else if(event.getReason().equals(Reason.CANCEL)){
673
                // noting to do
674
            }
675

    
676
        }
677
        // ignore other editors
678
    }
679

    
680

    
681
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationWorkingSet.class)
682
    public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent<RegistrationWorkingSet,?> event) {
683

    
684
        if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
685
            List<String> messages = new ArrayList<>();
686
            for(RegistrationDTO dto : workingset.getRegistrationDTOs()){
687
                dto.getValidationProblems().forEach(m -> messages.add(dto.getSummary() + ": " + m));
688
            }
689
            getView().openDetailsPopup("Validation Problems", messages);
690
        }
691
    }
692

    
693
    @EventBusListenerMethod
694
    public void onEntityChangeEvent(EntityChangeEvent event){
695

    
696
        if(workingset == null){
697
            return;
698
        }
699
        if(Reference.class.isAssignableFrom(event.getEntityType())){
700

    
701
            if(workingset.getCitationUuid().equals(event.getEntityUuid())){
702
                if(event.isRemovedType()){
703
                    viewEventBus.publish(EventScope.UI, this, new NavigationEvent(StartRegistrationViewBean.NAME));
704
                } else {
705
                    refreshView(true);
706
                }
707
            }
708

    
709
        } else
710
        if(Registration.class.isAssignableFrom(event.getEntityType())){
711
            if(workingset.getRegistrations().stream().anyMatch(reg -> reg.getUuid() == event.getEntityUuid())){
712
                refreshView(true);
713
            }
714
        } else
715
        if(TaxonName.class.isAssignableFrom(event.getEntityType())){
716
            if(event.getType().equals(EntityChangeEvent.Type.CREATED)){
717
                Stack<EditorActionContext>context = ((AbstractPopupEditor)event.getSourceView()).getEditorActionContext();
718
                EditorActionContext rootContext = context.get(0);
719
                if(rootContext.getParentView().equals(getView()) && event.getSourceView() != newNameForRegistrationPopupEditor){
720
                    try {
721
                        getRepo().getSession().clear();
722
                        // create a blocking registration, the new Registration will be persisted
723
                        UUID taxonNameUUID = event.getEntityUuid();
724

    
725
                        if(context.get(1).getParentView() instanceof TaxonNamePopupEditor && !((TaxonNamePopupEditor)context.get(1).getParentView()).getBean().cdmEntity().isPersited()){
726
                            // Oha!! The event came from a popup editor and the
727
                            // first popup in the context is a TaxonNameEditor with un-persisted name
728
                            // This is a name for a new registration which has not yet been created.
729
                            // It is necessary to store blocking registrations in the newNameBlockingRegistrations
730
                            Registration blockingRegistration = getRepo().getRegistrationService().createRegistrationForName(taxonNameUUID);
731
                            newNameBlockingRegistrations.add(blockingRegistration);
732
                            logger.debug("Blocking registration created and memorized");
733
                        } else {
734
                            Registration registration = findRegistrationInContext(context);
735
                            // some new name somehow related to an existing registration
736
                            registrationWorkflowService.addBlockingRegistration(taxonNameUUID, registration);
737
                        }
738
                    } finally {
739
                        getRepo().getSession().clear();
740
                    }
741

    
742
                } else {
743
                    // in case of creating a new name for a registration the parent view is the TaxonNamePopupEditor
744
                    // this is set
745
                    logger.debug("Non blocking registration, since a new name for a new registration has been created");
746
                }
747
            }
748
            if(workingset.getRegistrationDTOs().stream().anyMatch(reg ->
749
                reg.getTypifiedNameRef() != null
750
                && reg.getTypifiedNameRef().getUuid().equals(event.getEntityUuid()))){
751
                    refreshView(true);
752
            }
753
        } else
754
        if(TypeDesignationBase.class.isAssignableFrom(event.getEntityType())){
755
            if(workingset.getRegistrationDTOs().stream().anyMatch(
756
                    reg -> reg.typeDesignations() != null && reg.typeDesignations().stream().anyMatch(
757
                            td -> td.getUuid() == event.getEntityUuid()
758
                            )
759
                        )
760
                    ){
761
                refreshView(true);
762
            }
763
        }
764
    }
765

    
766
    public Registration findRegistrationInContext(PopupView popupView) {
767
        Stack<EditorActionContext>context = ((AbstractPopupEditor)popupView).getEditorActionContext();
768
        return findRegistrationInContext(context);
769
    }
770
    /**
771
     * Finds the Registration in the EditorContext stack
772
     *
773
     * @param context
774
     * @return
775
     */
776
    public Registration findRegistrationInContext(Stack<EditorActionContext> context) {
777
        EditorActionContext rootCtx = context.get(0);
778
        TypedEntityReference<Registration> regReference = (TypedEntityReference<Registration>)rootCtx.getParentEntity();
779
        RegistrationDTO registrationDTO = workingset.getRegistrationDTO(regReference.getUuid()).get();
780
        Registration registration = registrationDTO.registration();
781

    
782
        // registration = reloadRegistration(registration);
783
        return registration;
784
    }
785

    
786

    
787

    
788
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationDTO.class)
789
    public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent<RegistrationDTO, UUID> event) {
790

    
791
        // FIXME check from own view!!!
792
        if(getView() == null){
793
            return;
794
        }
795

    
796
        UUID registrationUuid = event.getIdentifier();
797

    
798
        RegistrationDTO regDto = workingset.getRegistrationDTO(registrationUuid).get();
799
        if(event.getProperty().equals(RegistrationItem.BLOCKED_BY)){
800

    
801
            Set<RegistrationDTO> blockingRegs;
802
            if(regDto.registration().isPersited()){
803
                blockingRegs = getWorkingSetService().loadBlockingRegistrations(registrationUuid);
804
            } else {
805
                blockingRegs = new HashSet<RegistrationDTO>(getWorkingSetService().makeDTOs(regDto.registration().getBlockedBy()));
806
            }
807
            getView().setBlockingRegistrations(registrationUuid, blockingRegs);
808
        } else if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
809
            getView().openDetailsPopup("Validation Problems", regDto.getValidationProblems());
810
        }
811
    }
812

    
813
    /**
814
     * {@inheritDoc}
815
     */
816
    @Override
817
    public ICdmEntityUuidCacher getCache() {
818
        return cache;
819
    }
820

    
821
    /**
822
     * {@inheritDoc}
823
     */
824
    @Override
825
    public void addRootEntity(CdmBase entity) {
826
        rootEntities.add(entity);
827
        cache.load(entity);
828
    }
829

    
830

    
831
    /**
832
     * {@inheritDoc}
833
     */
834
    @Override
835
    public Collection<CdmBase> getRootEntities() {
836
        return rootEntities;
837
    }
838

    
839
    @Override
840
    public void destroy() throws Exception {
841
        super.destroy();
842
        disposeCache();
843
    }
844

    
845
    /**
846
     * {@inheritDoc}
847
     */
848
    @Override
849
    public void disposeCache() {
850
        cache.dispose();
851
    }
852

    
853
    /**
854
     * @param name
855
     * @return
856
     */
857
    public boolean canCreateNameRegistrationFor(TaxonName name) {
858
        return registrationWorkflowService.canCreateNameRegistrationFor(workingset, name);
859
    }
860

    
861
    /**
862
     * @param name
863
     * @return
864
     */
865
    public boolean checkWokingsetContainsProtologe(TaxonName name) {
866
        return registrationWorkflowService.checkWokingsetContainsProtologe(workingset, name);
867
    }
868

    
869
}
(10-10/18)