Project

General

Profile

Download (33.9 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.EnumSet;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Objects;
17
import java.util.Set;
18
import java.util.Stack;
19
import java.util.UUID;
20

    
21
import org.apache.log4j.Logger;
22
import org.hibernate.Session;
23
import org.hibernate.Transaction;
24
import org.springframework.beans.factory.annotation.Autowired;
25
import org.springframework.security.core.Authentication;
26
import org.springframework.transaction.TransactionStatus;
27
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
28

    
29
import com.vaadin.server.SystemError;
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.Button;
34
import com.vaadin.ui.Label;
35
import com.vaadin.ui.UI;
36
import com.vaadin.ui.VerticalLayout;
37
import com.vaadin.ui.Window;
38

    
39
import eu.etaxonomy.cdm.api.service.INameService;
40
import eu.etaxonomy.cdm.api.service.IRegistrationService;
41
import eu.etaxonomy.cdm.api.service.config.RegistrationStatusTransitions;
42
import eu.etaxonomy.cdm.api.service.dto.EntityReference;
43
import eu.etaxonomy.cdm.api.service.dto.RegistrationDTO;
44
import eu.etaxonomy.cdm.api.service.dto.TypedEntityReference;
45
import eu.etaxonomy.cdm.api.service.exception.RegistrationValidationException;
46
import eu.etaxonomy.cdm.api.service.idminter.IdentifierMinter.Identifier;
47
import eu.etaxonomy.cdm.api.service.idminter.RegistrationIdentifierMinter;
48
import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager.TypeDesignationWorkingSetType;
49
import eu.etaxonomy.cdm.ext.common.ExternalServiceException;
50
import eu.etaxonomy.cdm.ext.registration.messages.IRegistrationMessageService;
51
import eu.etaxonomy.cdm.model.common.User;
52
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
53
import eu.etaxonomy.cdm.model.name.Rank;
54
import eu.etaxonomy.cdm.model.name.Registration;
55
import eu.etaxonomy.cdm.model.name.RegistrationStatus;
56
import eu.etaxonomy.cdm.model.name.TaxonName;
57
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
58
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
59
import eu.etaxonomy.cdm.model.reference.Reference;
60
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
61
import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;
62
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
63
import eu.etaxonomy.cdm.service.CdmStore;
64
import eu.etaxonomy.cdm.service.IRegistrationWorkingSetService;
65
import eu.etaxonomy.cdm.vaadin.component.CdmBeanItemContainerFactory;
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.AbstractEditorAction.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.model.registration.RegistrationWorkingSet;
80
import eu.etaxonomy.cdm.vaadin.permission.UserHelper;
81
import eu.etaxonomy.cdm.vaadin.theme.EditValoTheme;
82
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
83
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
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.TaxonNamePopupEditor;
87
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditorMode;
88
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditorView;
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.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> {
106

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

    
109
    private static final List<String> REGISTRATION_INIT_STRATEGY = Arrays.asList(
110
            "$",
111
            "blockedBy",
112
            "name.combinationAuthorship",
113
            "name.exCombinationAuthorship",
114
            "name.basionymAuthorship",
115
            "name.exBasionymAuthorship"
116
            );
117

    
118
    private static final long serialVersionUID = 1L;
119

    
120
    @Autowired
121
    private IRegistrationWorkingSetService regWorkingSetService;
122

    
123
    @Autowired
124
    private RegistrationIdentifierMinter minter;
125

    
126
    @Autowired
127
    private IRegistrationMessageService messageService;
128

    
129
    /**
130
     * @return the regWorkingSetService
131
     */
132
    public IRegistrationWorkingSetService getWorkingSetService() {
133
        return regWorkingSetService;
134
    }
135

    
136
    private RegistrationWorkingSet workingset;
137

    
138
    private TaxonName newTaxonNameForRegistration = null;
139

    
140
    private RegistrationDTO newRegistrationDTOWithExistingName;
141

    
142
    private RegistrationDTO newNameTypeDesignationTarget;
143

    
144

    
145
    /**
146
     *
147
     */
148
    public RegistrationWorkingsetPresenter() {
149
    }
150

    
151
    /**
152
     * Always create a new Store
153
     *
154
     * @return
155
     */
156
    protected CdmStore<Registration, IRegistrationService> getRegistrationStore(){
157
        return new CdmStore<Registration, IRegistrationService>(getRepo(), getRepo().getRegistrationService());
158
    }
159

    
160
    /**
161
     * Always create a new Store
162
     *
163
     * @return
164
     */
165
    protected CdmStore<TaxonName, INameService> getTaxonNameStore(){
166
        return new  CdmStore<TaxonName, INameService>(getRepo(), getRepo().getNameService());
167
    }
168

    
169

    
170
    /**
171
     * @param taxonNameId
172
     * @return
173
     */
174
    protected Registration createNewRegistrationForName(UUID taxonNameUuid) {
175
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176
        // move into RegistrationWorkflowStateMachine
177
        TransactionStatus txStatus = getRepo().startTransaction();
178

    
179
        Identifier<String> identifiers = minter.mint();
180
        if(identifiers.getIdentifier() == null){
181
            throw new RuntimeException("RegistrationIdentifierMinter configuration incomplete.");
182
        }
183
        Registration reg = Registration.NewInstance(
184
                identifiers.getIdentifier(),
185
                identifiers.getLocalId(),
186
                taxonNameUuid != null ? getRepo().getNameService().find(taxonNameUuid) : null,
187
                null);
188
        Authentication authentication = currentSecurityContext().getAuthentication();
189
        reg.setSubmitter((User)authentication.getPrincipal());
190
        EntityChangeEvent event = getRegistrationStore().saveBean(reg, (AbstractView) getView());
191
        UserHelper.fromSession().createAuthorityForCurrentUser(Registration.class, event.getEntityUuid(), Operation.UPDATE, RegistrationStatus.PREPARATION.name());
192
        getRepo().commitTransaction(txStatus);
193
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
194
        return getRepo().getRegistrationService().load(event.getEntityUuid(), Arrays.asList(new String []{"blockedBy"}));
195
    }
196

    
197
    /**
198
     * @param doReload TODO
199
     *
200
     */
201
    protected void refreshView(boolean doReload) {
202
        if(workingset == null){
203
            return; // nothing to do
204
        }
205
        if(doReload){
206
            loadWorkingSet(workingset.getCitationUuid());
207
        }
208
        applyWorkingset();
209
    }
210

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

    
221
            private static final long serialVersionUID = 7099181280977511048L;
222

    
223
            @Override
224
            public AbstractField<Object> create(RegistrationDTO regDto) {
225

    
226
                CdmBeanItemContainerFactory selectFieldFactory = new CdmBeanItemContainerFactory(getRepo());
227
                // submitters have GrantedAuthorities like REGISTRATION(PREPARATION).[UPDATE]{ab4459eb-3b96-40ba-bfaa-36915107d59e}
228
                UserHelper userHelper = UserHelper.fromSession();
229
                Set<RegistrationStatus> availableStatus = new HashSet<>();
230

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

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

    
251

    
252
        });
253
        loadWorkingSet(getView().getCitationUuid());
254
        applyWorkingset();
255

    
256
    }
257

    
258
    private void applyWorkingset(){
259
         getView().setWorkingset(workingset);
260
        // PagingProviders and CacheGenerator for the existingNameCombobox
261
        activateComboboxes();
262
        // update the messages
263
        updateMessages();
264
    }
265

    
266
    /**
267
     *
268
     */
269
    protected void activateComboboxes() {
270
        CdmFilterablePagingProvider<TaxonName, TaxonName> pagingProvider = new CdmFilterablePagingProvider<TaxonName, TaxonName>(
271
                getRepo().getNameService());
272
        // pagingProvider.addRestriction(new Restriction<>("registrations.identifier", true, MatchMode.BEGINNING, "http://phycobank.org/"));
273
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenerator = new CdmTitleCacheCaptionGenerator<TaxonName>();
274
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenerator);
275
        getView().getAddExistingNameCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
276
    }
277

    
278
    /**
279
     *
280
     */
281
    protected void updateMessages() {
282
        User user = UserHelper.fromSession().user();
283
        for (UUID registrationUuid : getView().getRegistrationItemMap().keySet()) {
284
            Button messageButton = getView().getRegistrationItemMap().get(registrationUuid).regItemButtons.getMessagesButton();
285

    
286
            RegistrationDTO regDto = workingset.getRegistrationDTO(registrationUuid).get();
287
            try {
288
                int messageCount = messageService.countActiveMessagesFor(regDto.registration(), user);
289

    
290
                boolean activeMessages = messageCount > 0;
291
                boolean currentUserIsSubmitter = regDto.getSubmitterUserName() != null && regDto.getSubmitterUserName().equals(UserHelper.fromSession().userName());
292
                boolean currentUserIsCurator = UserHelper.fromSession().userIsRegistrationCurator();
293
                messageButton.setEnabled(false);
294
                if(currentUserIsCurator){
295
                    if(currentUserIsSubmitter){
296
                        messageButton.setDescription("No point sending messages to your self.");
297
                    } else {
298
                        messageButton.setEnabled(true);
299
                        messageButton.setDescription("Open the messages dialog.");
300
                    }
301
                } else {
302
                    messageButton.setDescription("Sorry, only a curator can start a conversation.");
303
                }
304
                if(activeMessages){
305
                    messageButton.setEnabled(true);
306
                    messageButton.addStyleName(EditValoTheme.BUTTON_HIGHLITE);
307
                    String who = currentUserIsSubmitter ? "curator" : "submitter";
308
                    messageButton.setDescription("The " + who + " is looking forward to your reply.");
309

    
310
                }
311
            } catch (ExternalServiceException e) {
312
                messageButton.setComponentError(new SystemError(e.getMessage(), e));
313
            }
314
        }
315
    }
316

    
317

    
318
    /**
319
     * @param referenceID
320
     */
321
    protected void loadWorkingSet(UUID referenceUuid) {
322
        try {
323
            workingset = getWorkingSetService().loadWorkingSetByReferenceUuid(referenceUuid, true);
324
        } catch (RegistrationValidationException error) {
325
            logger.error(error);
326
            Window errorDialog = new Window("Validation Error");
327
            errorDialog.setModal(true);
328
            VerticalLayout subContent = new VerticalLayout();
329
            subContent.setMargin(true);
330
            errorDialog.setContent(subContent);
331
            subContent.addComponent(new Label(error.getMessage()));
332
            UI.getCurrent().addWindow(errorDialog);
333
        }
334
        if(workingset == null || workingset.getCitationUuid() == null){
335
            Reference citation = getRepo().getReferenceService().find(referenceUuid);
336
            workingset = new RegistrationWorkingSet(citation);
337
        }
338
    }
339

    
340
    private void saveRegistrationStatusChange(UUID uuid, Object value) {
341
        Registration reg = getRepo().getRegistrationService().load(uuid);
342
        if(value != null && value instanceof RegistrationStatus){
343
            if(!Objects.equals(value, reg.getStatus())){
344
                reg.setStatus((RegistrationStatus)value);
345
                getRegistrationStore().saveBean(reg, (AbstractView)getView());
346
                refreshView(true);
347
            }
348
        } else {
349
            // only log here as error
350
            logger.error("Ivalid attempt to set RegistrationStatus to " + Objects.toString(value.toString(), "NULL"));
351
        }
352
    }
353

    
354

    
355
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
356
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
357

    
358
        if(!checkFromOwnView(event)){
359
            return;
360
        }
361

    
362
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
363
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
364
        popup.loadInEditor(null);
365
    }
366

    
367
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
368
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
369

    
370
        if(!checkFromOwnView(event)){
371
            return;
372
        }
373
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
374
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
375
        popup.withDeleteButton(true);
376
        popup.loadInEditor(event.getEntityUuid());
377
    }
378

    
379
    @EventBusListenerMethod
380
    public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
381
        if(event.getPopup() instanceof ReferencePopupEditor){
382
            if(event.getReason().equals(Reason.SAVE)){
383
                refreshView(true);
384
            }
385
        }
386
    }
387

    
388
    @EventBusListenerMethod
389
    public void onDoneWithSpecimenTypeDesignationWorkingsetPopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
390
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
391
            if(event.getReason().equals(Reason.SAVE)){
392
                refreshView(true);
393
            }
394
        }
395
    }
396

    
397
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
398
    public void onRegistrationEditorAction(RegistrationEditorAction event) {
399

    
400
        if(!checkFromOwnView(event)){
401
            return;
402
        }
403

    
404
        RegistrationPopupEditor popup = openPopupEditor(RegistrationPopupEditor.class, event);
405
        popup.loadInEditor(event.getEntityUuid());
406
    }
407

    
408
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
409
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
410

    
411
        if(!checkFromOwnView(event)){
412
            return;
413
        }
414

    
415
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
416
        popup.setParentEditorActionContext(event.getContext());
417
        popup.withDeleteButton(true);
418
        configureTaxonNameEditor(popup);
419
        popup.loadInEditor(event.getEntityUuid());
420
        if(event.hasSource() && event.getSource().isReadOnly()){
421
            // avoid resetting readonly to false
422
            popup.setReadOnly(true);
423
        }
424

    
425
    }
426

    
427

    
428
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
429
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
430

    
431
        if(!checkFromOwnView(event)){
432
            return;
433
        }
434

    
435
        newTaxonNameForRegistration = TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
436
        newTaxonNameForRegistration.setNomenclaturalReference(getRepo().getReferenceService().find(workingset.getCitationUuid()));
437
        EntityChangeEvent nameSaveEvent = getTaxonNameStore().saveBean(newTaxonNameForRegistration, (AbstractView) getView());
438
        newTaxonNameForRegistration = getRepo().getNameService().find(nameSaveEvent.getEntityUuid());
439
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
440
        popup.setParentEditorActionContext(event.getContext());
441
        popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE,CRUD.DELETE));
442
        popup.withDeleteButton(true);
443
        configureTaxonNameEditor(popup);
444
        popup.loadInEditor(newTaxonNameForRegistration.getUuid());
445
    }
446

    
447
    /**
448
     * TODO consider putting this into a Configurer Bean per UIScope.
449
     * In the configurator bean this methods popup papamerter should be of the type
450
     * AbstractPopupEditor
451
     *
452
     * @param popup
453
     */
454
    protected void configureTaxonNameEditor(TaxonNamePopupEditorView popup) {
455
        popup.enableMode(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA);
456
        popup.enableMode(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
457
        popup.enableMode(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART);
458
        // popup.enableMode(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE);
459
    }
460

    
461
    /**
462
     * Creates a new <code>Registration</code> for a new name that has just been edited
463
     * using the <code>TaxonNamePopupEditor</code>. The new name was previously created
464
     * in this presenter as <code>newTaxonNameForRegistration</code> (see {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)})
465
     * and is either filled with data (<code>Reason.SAVE</code>) or it is still empty
466
     * (<code>Reason.CANCEL</code>).
467
     *
468
     *
469
     * @param event
470
     * @throws RegistrationValidationException
471
     */
472
    @EventBusListenerMethod
473
    public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
474
        if(event.getPopup() instanceof TaxonNamePopupEditor){
475
            TransactionStatus txStatus = getRepo().startTransaction();
476
            if(event.getReason().equals(Reason.SAVE)){
477
                if(newTaxonNameForRegistration != null){
478
                    UUID taxonNameUuid = newTaxonNameForRegistration.getUuid();
479
                    getRepo().getSession().refresh(newTaxonNameForRegistration);
480
                    Registration reg = createNewRegistrationForName(taxonNameUuid);
481
                    // reload workingset into current session
482
                    loadWorkingSet(workingset.getCitationUuid());
483
                    workingset.add(reg);
484
                }
485
                refreshView(true);
486
            } else if(event.getReason().equals(Reason.CANCEL)){
487
                if(newTaxonNameForRegistration != null){
488
                    // clean up
489
                    getTaxonNameStore().deleteBean(newTaxonNameForRegistration, (AbstractView) getView());
490
                }
491
            }
492
            getRepo().commitTransaction(txStatus);
493
            newTaxonNameForRegistration = null;
494
        }
495
    }
496

    
497

    
498
    /**
499
     * Creates a new Registration for an exiting (previously published name).
500
     *
501
     * @param event
502
     * @throws RegistrationValidationException
503
     */
504
    @EventBusListenerMethod
505
    public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event) throws RegistrationValidationException {
506

    
507
        if(!event.isStart()){
508
            return;
509
        }
510

    
511
        getView().getAddExistingNameCombobox().commit();
512
        TaxonName typifiedName = getView().getAddExistingNameCombobox().getValue();
513
        if(typifiedName != null){
514
            Registration newRegistrationWithExistingName = createNewRegistrationForName(null);
515
            Reference citation = getRepo().getReferenceService().find(workingset.getCitationUuid());
516
            newRegistrationDTOWithExistingName = new RegistrationDTO(newRegistrationWithExistingName, typifiedName, citation);
517
            workingset.add(newRegistrationDTOWithExistingName);
518
            // tell the view to update the workingset
519
            getView().setWorkingset(workingset);
520
            getView().getAddExistingNameRegistrationButton().setEnabled(false);
521
            getView().getAddExistingNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
522
        } else {
523
            logger.error("Seletced name is NULL");
524
        }
525

    
526
    }
527

    
528

    
529
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
530
    public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event) {
531

    
532
        if(!checkFromOwnView(event)){
533
            return;
534
        }
535

    
536
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET ){
537
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
538
            popup.setParentEditorActionContext(event.getContext());
539
            popup.withDeleteButton(true);
540
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
541
            if(event.hasSource()){
542
                // propagate readonly state from source button to popup
543
                popup.setReadOnly(event.getSource().isReadOnly());
544
            }
545
        } else {
546
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
547
            popup.setParentEditorActionContext(event.getContext());
548
            popup.withDeleteButton(true);
549
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
550

    
551
            popup.getCitationCombobox().setEnabled(false);
552
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
553

    
554
            if(event.hasSource()){
555
                // propagate readonly state from source button to popup
556
                popup.setReadOnly(event.getSource().isReadOnly());
557
            }
558
            newNameTypeDesignationTarget = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
559
        }
560
    }
561

    
562
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
563
    public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event) {
564

    
565
        if(!event.hasSource()){
566
            return;
567
        }
568

    
569
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET){
570
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
571
            popup.setParentEditorActionContext(event.getContext());
572
            TypeDesignationWorkingsetEditorIdSet identifierSet;
573
            UUID typifiedNameUuid;
574
            if(newRegistrationDTOWithExistingName != null){
575
                typifiedNameUuid = newRegistrationDTOWithExistingName.getTypifiedNameRef().getUuid();
576
            } else {
577
                RegistrationDTO registrationDTO = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
578
                EntityReference typifiedNameRef = registrationDTO.getTypifiedNameRef();
579
                if(typifiedNameRef != null){
580
                    // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
581
                    typifiedNameUuid = typifiedNameRef.getUuid();
582
                } else {
583
                    // case of registrations with a name in the nomenclatural act.
584
                    typifiedNameUuid = registrationDTO.getNameRef().getUuid();
585
                }
586
            }
587
            identifierSet = new TypeDesignationWorkingsetEditorIdSet(
588
                    event.getRegistrationUuid(),
589
                    getView().getCitationUuid(),
590
                    typifiedNameUuid
591
                    );
592
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
593
            popup.loadInEditor(identifierSet);
594
            popup.withDeleteButton(true);
595
            if(event.hasSource()){
596
                // propagate readonly state from source component to popup
597
                popup.setReadOnly(event.getSource().isReadOnly());
598
            }
599
        } else {
600
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
601
            popup.setParentEditorActionContext(event.getContext());
602
            popup.withDeleteButton(true);
603
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
604
            newNameTypeDesignationTarget = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
605
            popup.setBeanInstantiator(new BeanInstantiator<NameTypeDesignation>() {
606

    
607
                @Override
608
                public NameTypeDesignation createNewBean() {
609

    
610
                    TaxonName typifiedName = getRepo().getNameService().load(event.getTypifiedNameUuid(), Arrays.asList(new String[]{"typeDesignations", "homotypicalGroup"}));
611
                    NameTypeDesignation nameTypeDesignation  = NameTypeDesignation.NewInstance();
612
                    nameTypeDesignation.setCitation(newNameTypeDesignationTarget.getCitation());
613
                    nameTypeDesignation.getTypifiedNames().add(typifiedName);
614
                    return nameTypeDesignation;
615
                }
616
            });
617
            popup.loadInEditor(null);
618
            popup.getCitationCombobox().setEnabled(false);
619
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
620
            if(event.hasSource()){
621
                // propagate readonly state from source component to popup
622
                popup.setReadOnly(event.getSource().isReadOnly());
623
            }
624
        }
625
    }
626

    
627
    /**
628
     * Performs final actions after a TypeDesignationEditor which has been
629
     * opened to add a TypeDesignation to a Registration object which was
630
     * created for an previously published name. Prior adding a typedesignation,
631
     * the according Registration object is dangling, that has no association to
632
     * any entity denoting an nomenclatural act which has a reference to a
633
     * publication. This means that the registration object is not in the
634
     * working set.
635
     *
636
     *
637
     * @param event
638
     * @throws RegistrationValidationException
639
     */
640
    @EventBusListenerMethod
641
    public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
642
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
643
            if(event.getReason().equals(Reason.SAVE)){
644
                refreshView(true);
645
            } else if(event.getReason().equals(Reason.CANCEL)){
646
                // noting to do
647
            }
648
            newRegistrationDTOWithExistingName = null;
649
        } else if(event.getPopup() instanceof NameTypeDesignationPopupEditor){
650
            if(event.getReason().equals(Reason.SAVE)){
651
                UUID uuid = ((NameTypeDesignationPopupEditor)event.getPopup()).getBean().getUuid();
652

    
653
                Session session = getRepo().getSessionFactory().openSession();
654
                Transaction txstate = session.beginTransaction();
655
                TypeDesignationBase<?> nameTypeDesignation = getRepo().getNameService().loadTypeDesignation(uuid, Arrays.asList(""));
656
                // only load the typeDesignations with the registration so that the typified name can  not be twice in the session
657
                // otherwise multiple representation problems might occur
658
                Registration registration = getRepo().getRegistrationService().load(newNameTypeDesignationTarget.getUuid(), Arrays.asList("typeDesignations"));
659
                registration.getTypeDesignations().add(nameTypeDesignation);
660
                session.merge(registration);
661
                txstate.commit();
662
                session.close();
663

    
664
                refreshView(true);
665
            } else if(event.getReason().equals(Reason.CANCEL)){
666
                // noting to do
667
            }
668
            newNameTypeDesignationTarget = null;
669
        }
670
        // ignore other editors
671
    }
672

    
673

    
674
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationWorkingSet.class)
675
    public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent<RegistrationWorkingSet,?> event) {
676

    
677
        if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
678
            List<String> messages = new ArrayList<>();
679
            for(RegistrationDTO dto : workingset.getRegistrationDTOs()){
680
                dto.getValidationProblems().forEach(m -> messages.add(dto.getSummary() + ": " + m));
681
            }
682
            getView().openDetailsPopup("Validation Problems", messages);
683
        }
684
    }
685

    
686
    @EventBusListenerMethod
687
    public void onEntityChangeEvent(EntityChangeEvent event){
688

    
689
        if(workingset == null){
690
            return;
691
        }
692
        if(Reference.class.isAssignableFrom(event.getEntityType())){
693
            if(workingset.getCitationUuid().equals(event.getEntityUuid())){
694
                refreshView(true);
695
            }
696
        } else
697
        if(Registration.class.isAssignableFrom(event.getEntityType())){
698
            if(workingset.getRegistrations().stream().anyMatch(reg -> reg.getUuid() == event.getEntityUuid())){
699
                refreshView(true);
700
            }
701
        } else
702
        if(TaxonName.class.isAssignableFrom(event.getEntityType()) && isFromOwnView(event)){
703
            if(event.getType().equals(EntityChangeEvent.Type.CREATED)){
704
                // new name! create a blocking registration
705
                Stack<EditorActionContext>context = ((AbstractPopupEditor)event.getSourceView()).getEditorActionContext();
706
                EditorActionContext rootContext = context.get(0);
707
                if(rootContext.getParentView().equals(getView())){
708
                    Registration blockingRegistration = createNewRegistrationForName(event.getEntityUuid());
709
                    TypedEntityReference<Registration> regReference = (TypedEntityReference<Registration>)rootContext.getParentEntity();
710
                    Registration registration = getRepo().getRegistrationService().load(regReference.getUuid(), REGISTRATION_INIT_STRATEGY);
711
                    registration.getBlockedBy().add(blockingRegistration);
712
                    getRepo().getRegistrationService().saveOrUpdate(registration);
713
                    logger.debug("Blocking registration created");
714
                } else {
715
                    logger.debug("Non blocking registration, since a new name for a new registration has been created");
716
                }
717
            }
718
            if(workingset.getRegistrationDTOs().stream().anyMatch(reg ->
719
                reg.getTypifiedNameRef() != null
720
                && reg.getTypifiedNameRef().getUuid().equals(event.getEntityUuid()))){
721
                    refreshView(true);
722
            }
723
        } else
724
        if(TypeDesignationBase.class.isAssignableFrom(event.getEntityType())){
725
            if(workingset.getRegistrationDTOs().stream().anyMatch(
726
                    reg -> reg.getTypeDesignations() != null && reg.getTypeDesignations().stream().anyMatch(
727
                            td -> td.getUuid() == event.getEntityUuid()
728
                            )
729
                        )
730
                    ){
731
                refreshView(true);
732
            }
733
        }
734
    }
735

    
736

    
737
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationDTO.class)
738
    public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent<RegistrationDTO, UUID> event) {
739

    
740
        // FIXME check from own view!!!
741
        if(getView() == null){
742
            return;
743
        }
744

    
745
        UUID registrationUuid = event.getIdentifier();
746

    
747
        RegistrationDTO regDto = getWorkingSetService().loadDtoByUuid(registrationUuid);
748
        if(event.getProperty().equals(RegistrationItem.BLOCKED_BY)){
749

    
750
            Set<RegistrationDTO> blockingRegs = getWorkingSetService().loadBlockingRegistrations(registrationUuid);
751
            getView().setBlockingRegistrations(registrationUuid, blockingRegs);
752
        } else if(event.getProperty().equals(RegistrationItem.MESSAGES)){
753

    
754
            RegistrationMessagesPopup popup = openPopupEditor(RegistrationMessagesPopup.class, null);
755
            popup.loadMessagesFor(regDto.getUuid());
756

    
757
        } else if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
758
            getView().openDetailsPopup("Validation Problems", regDto.getValidationProblems());
759
        }
760

    
761

    
762
    }
763

    
764
}
(12-12/19)