Project

General

Profile

Download (36.1 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.RegistrationDTO;
43
import eu.etaxonomy.cdm.api.service.dto.RegistrationWorkingSet;
44
import eu.etaxonomy.cdm.api.service.exception.RegistrationValidationException;
45
import eu.etaxonomy.cdm.api.service.idminter.IdentifierMinter.Identifier;
46
import eu.etaxonomy.cdm.api.service.idminter.RegistrationIdentifierMinter;
47
import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager.TypeDesignationWorkingSetType;
48
import eu.etaxonomy.cdm.api.service.registration.IRegistrationWorkingSetService;
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.model.reference.ReferenceType;
61
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
62
import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;
63
import eu.etaxonomy.cdm.ref.EntityReference;
64
import eu.etaxonomy.cdm.ref.TypedEntityReference;
65
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
66
import eu.etaxonomy.cdm.service.CdmStore;
67
import eu.etaxonomy.cdm.vaadin.component.CdmBeanItemContainerFactory;
68
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationItem;
69
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStatusFieldInstantiator;
70
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStatusSelect;
71
import eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.EditorActionContext;
72
import eu.etaxonomy.cdm.vaadin.event.EditorActionTypeFilter;
73
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
74
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
75
import eu.etaxonomy.cdm.vaadin.event.RegistrationEditorAction;
76
import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEvent;
77
import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEventEntityTypeFilter;
78
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
79
import eu.etaxonomy.cdm.vaadin.event.TypeDesignationWorkingsetEditorAction;
80
import eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkingsetAction;
81
import eu.etaxonomy.cdm.vaadin.permission.VaadinUserHelper;
82
import eu.etaxonomy.cdm.vaadin.theme.EditValoTheme;
83
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
84
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
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.TaxonNamePopupEditor;
88
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditorMode;
89
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditorView;
90
import eu.etaxonomy.cdm.vaadin.view.name.TypeDesignationWorkingsetEditorIdSet;
91
import eu.etaxonomy.cdm.vaadin.view.reference.ReferencePopupEditor;
92
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
93
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
94
import eu.etaxonomy.vaadin.mvp.AbstractView;
95
import eu.etaxonomy.vaadin.mvp.BeanInstantiator;
96
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
97
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent.Reason;
98

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

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

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

    
119
    private static final long serialVersionUID = 1L;
120

    
121
    @Autowired
122
    private IRegistrationWorkingSetService regWorkingSetService;
123

    
124
    @Autowired
125
    private RegistrationIdentifierMinter minter;
126

    
127
    @Autowired
128
    private IRegistrationMessageService messageService;
129

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

    
137
    private RegistrationWorkingSet workingset;
138

    
139
    private TaxonName newTaxonNameForRegistration = null;
140

    
141
    private RegistrationDTO newRegistrationDTOWithExistingName;
142

    
143
    private RegistrationDTO newNameTypeDesignationTarget;
144

    
145

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

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

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

    
170

    
171
    public boolean canCreateRegistrationForName(TaxonName name) {
172
        for(Registration reg : name.getRegistrations()){
173
            if(minter.isFromOwnRegistration(reg.getIdentifier())){
174
                return false;
175
            }
176
        }
177
        Reference nomRef = name.getNomenclaturalReference();
178
        UUID citationUuid = workingset.getCitationUuid();
179
        // @formatter:off
180
        return nomRef != null && (
181
                // nomref matches
182
                nomRef.getUuid().equals(citationUuid) ||
183
                // nomref.inreference matches
184
                (nomRef.getType() != null && nomRef.getType() == ReferenceType.Section && nomRef.getInReference() != null && nomRef.getInReference().getUuid().equals(citationUuid))
185
                );
186
        // @formatter:on
187
    }
188

    
189

    
190
    /**
191
     * @param taxonNameId
192
     * @return
193
     */
194
    protected Registration createNewRegistrationForName(UUID taxonNameUuid) {
195
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196
        // move into RegistrationWorkflowStateMachine
197
        TransactionStatus txStatus = getRepo().startTransaction();
198

    
199
        Identifier<String> identifiers = minter.mint();
200
        if(identifiers.getIdentifier() == null){
201
            throw new RuntimeException("RegistrationIdentifierMinter configuration incomplete.");
202
        }
203
        Registration reg = Registration.NewInstance(
204
                identifiers.getIdentifier(),
205
                identifiers.getLocalId(),
206
                taxonNameUuid != null ? getRepo().getNameService().load(taxonNameUuid, Arrays.asList("nomenclaturalReference.inReference")) : null,
207
                null);
208
        Authentication authentication = currentSecurityContext().getAuthentication();
209
        reg.setSubmitter((User)authentication.getPrincipal());
210
        EntityChangeEvent event = getRegistrationStore().saveBean(reg, (AbstractView) getView());
211
        VaadinUserHelper.fromSession().createAuthorityForCurrentUser(Registration.class, event.getEntityUuid(), Operation.UPDATE, RegistrationStatus.PREPARATION.name());
212
        getRepo().commitTransaction(txStatus);
213
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
214
        return getRepo().getRegistrationService().load(event.getEntityUuid(), Arrays.asList(new String []{"blockedBy"}));
215
    }
216

    
217
    /**
218
     * @param doReload TODO
219
     *
220
     */
221
    protected void refreshView(boolean doReload) {
222
        if(workingset == null){
223
            return; // nothing to do
224
        }
225
        if(doReload){
226
            loadWorkingSet(workingset.getCitationUuid());
227
        }
228
        applyWorkingset();
229
    }
230

    
231
    /**
232
     * {@inheritDoc}
233
     */
234
    @Override
235
    public void handleViewEntered() {
236
        super.handleViewEntered();
237
        // TODO currently cannot specify type more precisely, see AbstractSelect
238
        // FIXME externalize into class file!!!!!!!!!!!!
239
        getView().setStatusComponentInstantiator(new RegistrationStatusFieldInstantiator<Object>(){
240

    
241
            private static final long serialVersionUID = 7099181280977511048L;
242

    
243
            @Override
244
            public AbstractField<Object> create(RegistrationDTO regDto) {
245

    
246
                CdmBeanItemContainerFactory selectFieldFactory = new CdmBeanItemContainerFactory(getRepo());
247
                // submitters have GrantedAuthorities like REGISTRATION(PREPARATION).[UPDATE]{ab4459eb-3b96-40ba-bfaa-36915107d59e}
248
                VaadinUserHelper userHelper = VaadinUserHelper.fromSession();
249
                Set<RegistrationStatus> availableStatus = new HashSet<>();
250

    
251
                boolean canChangeStatus = userHelper.userHasPermission(regDto.registration(), CRUD.UPDATE);
252
                availableStatus.add(regDto.getStatus());
253
                if(canChangeStatus){
254
                    if(userHelper.userIsAdmin()){
255
                        availableStatus.addAll(Arrays.asList(RegistrationStatus.values()));
256
                    } else {
257
                        availableStatus.addAll(RegistrationStatusTransitions.possibleTransitions(regDto.getStatus()));
258
                    }
259
                }
260

    
261
                RegistrationStatusSelect select = new RegistrationStatusSelect(null, selectFieldFactory.buildBeanItemContainer(
262
                        RegistrationStatus.class,
263
                        availableStatus.toArray(new RegistrationStatus[availableStatus.size()]))
264
                        );
265
                select.addValueChangeListener(e -> saveRegistrationStatusChange(regDto.getUuid(), e.getProperty().getValue()));
266
                select.setEnabled(canChangeStatus);
267
                select.setNullSelectionAllowed(false);
268
                return select;
269
            }
270

    
271

    
272
        });
273
        loadWorkingSet(getView().getCitationUuid());
274
        applyWorkingset();
275

    
276
    }
277

    
278
    private void applyWorkingset(){
279
         getView().setWorkingset(workingset);
280
        // PagingProviders and CacheGenerator for the existingNameCombobox
281
        activateComboboxes();
282
        // update the messages
283
        updateMessages();
284
    }
285

    
286
    /**
287
     *
288
     */
289
    protected void activateComboboxes() {
290
        CdmFilterablePagingProvider<TaxonName, TaxonName> pagingProvider = new CdmFilterablePagingProvider<TaxonName, TaxonName>(
291
                getRepo().getNameService());
292
        pagingProvider.setInitStrategy(Arrays.asList("registrations", "nomenclaturalReference"));
293
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenerator = new CdmTitleCacheCaptionGenerator<TaxonName>();
294
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenerator);
295
        getView().getAddExistingNameCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
296
    }
297

    
298
    /**
299
     *
300
     */
301
    protected void updateMessages() {
302
        User user = VaadinUserHelper.fromSession().user();
303
        for (UUID registrationUuid : getView().getRegistrationItemMap().keySet()) {
304
            Button messageButton = getView().getRegistrationItemMap().get(registrationUuid).regItemButtons.getMessagesButton();
305

    
306
            RegistrationDTO regDto = workingset.getRegistrationDTO(registrationUuid).get();
307
            try {
308
                int messageCount = messageService.countActiveMessagesFor(regDto.registration(), user);
309

    
310
                boolean activeMessages = messageCount > 0;
311
                boolean currentUserIsSubmitter = regDto.getSubmitterUserName() != null && regDto.getSubmitterUserName().equals(VaadinUserHelper.fromSession().userName());
312
                boolean currentUserIsCurator = VaadinUserHelper.fromSession().userIsRegistrationCurator();
313
                messageButton.setEnabled(false);
314
                if(currentUserIsCurator){
315
                    if(currentUserIsSubmitter){
316
                        messageButton.setDescription("No point sending messages to your self.");
317
                    } else {
318
                        messageButton.setEnabled(true);
319
                        messageButton.setDescription("Open the messages dialog.");
320
                    }
321
                } else {
322
                    messageButton.setDescription("Sorry, only a curator can start a conversation.");
323
                }
324
                if(activeMessages){
325
                    messageButton.setEnabled(true);
326
                    messageButton.addStyleName(EditValoTheme.BUTTON_HIGHLITE);
327
                    String who = currentUserIsSubmitter ? "curator" : "submitter";
328
                    messageButton.setDescription("The " + who + " is looking forward to your reply.");
329

    
330
                }
331
            } catch (ExternalServiceException e) {
332
                messageButton.setComponentError(new SystemError(e.getMessage(), e));
333
            }
334
        }
335
    }
336

    
337

    
338
    /**
339
     * @param referenceID
340
     */
341
    protected void loadWorkingSet(UUID referenceUuid) {
342
        try {
343
            workingset = getWorkingSetService().loadWorkingSetByReferenceUuid(referenceUuid, true);
344
        } catch (RegistrationValidationException error) {
345
            logger.error(error);
346
            Window errorDialog = new Window("Validation Error");
347
            errorDialog.setModal(true);
348
            VerticalLayout subContent = new VerticalLayout();
349
            subContent.setMargin(true);
350
            errorDialog.setContent(subContent);
351
            subContent.addComponent(new Label(error.getMessage()));
352
            UI.getCurrent().addWindow(errorDialog);
353
        }
354
        if(workingset == null || workingset.getCitationUuid() == null){
355
            Reference citation = getRepo().getReferenceService().find(referenceUuid);
356
            workingset = new RegistrationWorkingSet(citation);
357
        }
358
    }
359

    
360
    private void saveRegistrationStatusChange(UUID uuid, Object value) {
361
        Registration reg = getRepo().getRegistrationService().load(uuid);
362
        if(value != null && value instanceof RegistrationStatus){
363
            if(!Objects.equals(value, reg.getStatus())){
364
                reg.setStatus((RegistrationStatus)value);
365
                getRegistrationStore().saveBean(reg, (AbstractView)getView());
366
                refreshView(true);
367
            }
368
        } else {
369
            // only log here as error
370
            logger.error("Ivalid attempt to set RegistrationStatus to " + Objects.toString(value.toString(), "NULL"));
371
        }
372
    }
373

    
374

    
375
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
376
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
377

    
378
        if(!checkFromOwnView(event)){
379
            return;
380
        }
381

    
382
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
383
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
384
        popup.loadInEditor(null);
385
    }
386

    
387
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
388
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
389

    
390
        if(!checkFromOwnView(event)){
391
            return;
392
        }
393
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
394
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
395
        popup.withDeleteButton(true);
396
        popup.loadInEditor(event.getEntityUuid());
397
    }
398

    
399
    @EventBusListenerMethod
400
    public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
401
        if(event.getPopup() instanceof ReferencePopupEditor){
402
            if(event.getReason().equals(Reason.SAVE)){
403
                refreshView(true);
404
            }
405
        }
406
    }
407

    
408
    @EventBusListenerMethod
409
    public void onDoneWithSpecimenTypeDesignationWorkingsetPopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
410
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
411
            if(event.getReason().equals(Reason.SAVE)){
412
                refreshView(true);
413
            }
414
        }
415
    }
416

    
417
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
418
    public void onRegistrationEditorAction(RegistrationEditorAction event) {
419

    
420
        if(!checkFromOwnView(event)){
421
            return;
422
        }
423

    
424
        RegistrationPopupEditor popup = openPopupEditor(RegistrationPopupEditor.class, event);
425
        popup.loadInEditor(event.getEntityUuid());
426
    }
427

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

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

    
435
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
436
        popup.setParentEditorActionContext(event.getContext());
437
        popup.withDeleteButton(true);
438
        configureTaxonNameEditor(popup);
439
        popup.loadInEditor(event.getEntityUuid());
440
        if(event.hasSource() && event.getSource().isReadOnly()){
441
            // avoid resetting readonly to false
442
            popup.setReadOnly(true);
443
        }
444

    
445
    }
446

    
447

    
448
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
449
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
450

    
451
        if(!checkFromOwnView(event)){
452
            return;
453
        }
454

    
455
        newTaxonNameForRegistration = TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
456
        newTaxonNameForRegistration.setNomenclaturalReference(getRepo().getReferenceService().find(workingset.getCitationUuid()));
457
        EntityChangeEvent nameSaveEvent = getTaxonNameStore().saveBean(newTaxonNameForRegistration, (AbstractView) getView());
458
        newTaxonNameForRegistration = getRepo().getNameService().find(nameSaveEvent.getEntityUuid());
459
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
460
        popup.setParentEditorActionContext(event.getContext());
461
        popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE,CRUD.DELETE));
462
        popup.withDeleteButton(true);
463
        configureTaxonNameEditor(popup);
464
        popup.loadInEditor(newTaxonNameForRegistration.getUuid());
465
    }
466

    
467
    /**
468
     * TODO consider putting this into a Configurer Bean per UIScope.
469
     * In the configurator bean this methods popup papamerter should be of the type
470
     * AbstractPopupEditor
471
     *
472
     * @param popup
473
     */
474
    protected void configureTaxonNameEditor(TaxonNamePopupEditorView popup) {
475
        popup.enableMode(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA);
476
        popup.enableMode(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
477
        popup.enableMode(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART);
478
        // popup.enableMode(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE);
479
    }
480

    
481
    /**
482
     * Creates a new <code>Registration</code> for a new name that has just been edited
483
     * using the <code>TaxonNamePopupEditor</code>. The new name was previously created
484
     * in this presenter as <code>newTaxonNameForRegistration</code> (see {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)})
485
     * and is either filled with data (<code>Reason.SAVE</code>) or it is still empty
486
     * (<code>Reason.CANCEL</code>).
487
     *
488
     *
489
     * @param event
490
     * @throws RegistrationValidationException
491
     */
492
    @EventBusListenerMethod
493
    public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
494
        if(event.getPopup() instanceof TaxonNamePopupEditor){
495
            TransactionStatus txStatus = getRepo().startTransaction();
496
            if(event.getReason().equals(Reason.SAVE)){
497
                if(newTaxonNameForRegistration != null){
498
                    UUID taxonNameUuid = newTaxonNameForRegistration.getUuid();
499
                    getRepo().getSession().refresh(newTaxonNameForRegistration);
500
                    Registration reg = createNewRegistrationForName(taxonNameUuid);
501
                    // reload workingset into current session
502
                    loadWorkingSet(workingset.getCitationUuid());
503
                    workingset.add(reg);
504
                }
505
                refreshView(true);
506
            } else if(event.getReason().equals(Reason.CANCEL)){
507
                if(newTaxonNameForRegistration != null){
508
                    // clean up
509
                    getTaxonNameStore().deleteBean(newTaxonNameForRegistration, (AbstractView) getView());
510
                }
511
            }
512
            getRepo().commitTransaction(txStatus);
513
            newTaxonNameForRegistration = null;
514
        }
515
    }
516

    
517

    
518
    /**
519
     * Creates a new Registration for an exiting (previously published name).
520
     *
521
     * @param event
522
     * @throws RegistrationValidationException
523
     */
524
    @EventBusListenerMethod
525
    public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event) throws RegistrationValidationException {
526

    
527
        if(!event.isStart()){
528
            return;
529
        }
530

    
531
        getView().getAddExistingNameCombobox().commit();
532
        TaxonName typifiedName = getView().getAddExistingNameCombobox().getValue();
533
        if(typifiedName != null){
534
            boolean reloadWorkingSet = false;
535
            Reference citation = getRepo().getReferenceService().find(workingset.getCitationUuid());
536
            if(event.getType() == ExistingNameRegistrationType.NAME_TYPIFICATION && canCreateRegistrationForName(typifiedName)){
537
                Registration newRegistrationWithExistingName = createNewRegistrationForName(typifiedName.getUuid());
538
                newRegistrationDTOWithExistingName = new RegistrationDTO(newRegistrationWithExistingName, typifiedName, citation);
539
                reloadWorkingSet = true;
540
            } else {
541
                // case: ExistingNameRegistrationType.TYPIFICATION_ONLY
542
                Registration newRegistrationWithExistingName = createNewRegistrationForName(null);
543
                newRegistrationDTOWithExistingName = new RegistrationDTO(newRegistrationWithExistingName, typifiedName, citation);
544
                Registration blockingRegistration = createNewRegistrationForName(typifiedName.getUuid());
545
                newRegistrationWithExistingName.getBlockedBy().add(blockingRegistration);
546
            }
547
            workingset.add(newRegistrationDTOWithExistingName);
548
            // tell the view to update the workingset
549
            refreshView(reloadWorkingSet);
550
            getView().getAddExistingNameRegistrationButton().setEnabled(false);
551
            if(newRegistrationDTOWithExistingName.registration().getName() == null){
552
                getView().getAddExistingNameCombobox().setEnabled(false);
553
                getView().getAddNewNameRegistrationButton().setEnabled(false);
554
                getView().getAddNewNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
555
                getView().getAddExistingNameCombobox().setDescription("You first need to add a type designation to the previously created registration.");
556
                getView().getAddExistingNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
557
            }
558
        } else {
559
            logger.error("Seletced name is NULL");
560
        }
561

    
562
    }
563

    
564

    
565
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
566
    public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event) {
567

    
568
        if(!checkFromOwnView(event)){
569
            return;
570
        }
571

    
572
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET ){
573
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
574
            popup.setParentEditorActionContext(event.getContext());
575
            popup.withDeleteButton(true);
576
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
577
            if(event.hasSource()){
578
                // propagate readonly state from source button to popup
579
                popup.setReadOnly(event.getSource().isReadOnly());
580
            }
581
        } else {
582
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
583
            popup.setParentEditorActionContext(event.getContext());
584
            popup.withDeleteButton(true);
585
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
586

    
587
            popup.getCitationCombobox().setEnabled(false);
588
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
589

    
590
            if(event.hasSource()){
591
                // propagate readonly state from source button to popup
592
                popup.setReadOnly(event.getSource().isReadOnly());
593
            }
594
            newNameTypeDesignationTarget = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
595
        }
596
    }
597

    
598
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
599
    public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event) {
600

    
601
        if(!event.hasSource()){
602
            return;
603
        }
604

    
605
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET){
606
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
607
            popup.setParentEditorActionContext(event.getContext());
608
            TypeDesignationWorkingsetEditorIdSet identifierSet;
609
            UUID typifiedNameUuid;
610
            if(newRegistrationDTOWithExistingName != null){
611
                typifiedNameUuid = newRegistrationDTOWithExistingName.getTypifiedNameRef().getUuid();
612
            } else {
613
                RegistrationDTO registrationDTO = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
614
                EntityReference typifiedNameRef = registrationDTO.getTypifiedNameRef();
615
                if(typifiedNameRef != null){
616
                    // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
617
                    typifiedNameUuid = typifiedNameRef.getUuid();
618
                } else {
619
                    // case of registrations with a name in the nomenclatural act.
620
                    typifiedNameUuid = registrationDTO.getNameRef().getUuid();
621
                }
622
            }
623
            identifierSet = new TypeDesignationWorkingsetEditorIdSet(
624
                    event.getRegistrationUuid(),
625
                    getView().getCitationUuid(),
626
                    typifiedNameUuid
627
                    );
628
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
629
            popup.loadInEditor(identifierSet);
630
            popup.withDeleteButton(true);
631
            if(event.hasSource()){
632
                // propagate readonly state from source component to popup
633
                popup.setReadOnly(event.getSource().isReadOnly());
634
            }
635
        } else {
636
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
637
            popup.setParentEditorActionContext(event.getContext());
638
            popup.withDeleteButton(true);
639
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
640
            newNameTypeDesignationTarget = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
641
            popup.setBeanInstantiator(new BeanInstantiator<NameTypeDesignation>() {
642

    
643
                @Override
644
                public NameTypeDesignation createNewBean() {
645

    
646
                    TaxonName typifiedName = getRepo().getNameService().load(event.getTypifiedNameUuid(), Arrays.asList(new String[]{"typeDesignations", "homotypicalGroup"}));
647
                    NameTypeDesignation nameTypeDesignation  = NameTypeDesignation.NewInstance();
648
                    nameTypeDesignation.setCitation(newNameTypeDesignationTarget.getCitation());
649
                    nameTypeDesignation.getTypifiedNames().add(typifiedName);
650
                    return nameTypeDesignation;
651
                }
652
            });
653
            popup.loadInEditor(null);
654
            popup.getCitationCombobox().setEnabled(false);
655
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
656
            if(event.hasSource()){
657
                // propagate readonly state from source component to popup
658
                popup.setReadOnly(event.getSource().isReadOnly());
659
            }
660
        }
661
    }
662

    
663
    /**
664
     * Performs final actions after a TypeDesignationEditor which has been
665
     * opened to add a TypeDesignation to a Registration object which was
666
     * created for an previously published name. Prior adding a typedesignation,
667
     * the according Registration object is dangling, that has no association to
668
     * any entity denoting an nomenclatural act which has a reference to a
669
     * publication. This means that the registration object is not in the
670
     * working set.
671
     *
672
     *
673
     * @param event
674
     * @throws RegistrationValidationException
675
     */
676
    @EventBusListenerMethod
677
    public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
678
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
679
            if(event.getReason().equals(Reason.SAVE)){
680
                refreshView(true);
681
            } else if(event.getReason().equals(Reason.CANCEL)){
682
                // noting to do
683
            }
684
            newRegistrationDTOWithExistingName = null;
685
        } else if(event.getPopup() instanceof NameTypeDesignationPopupEditor){
686
            if(event.getReason().equals(Reason.SAVE)){
687
                UUID uuid = ((NameTypeDesignationPopupEditor)event.getPopup()).getBean().getUuid();
688

    
689
                Session session = getRepo().getSessionFactory().openSession();
690
                Transaction txstate = session.beginTransaction();
691
                TypeDesignationBase<?> nameTypeDesignation = getRepo().getNameService().loadTypeDesignation(uuid, Arrays.asList(""));
692
                // only load the typeDesignations with the registration so that the typified name can  not be twice in the session
693
                // otherwise multiple representation problems might occur
694
                Registration registration = getRepo().getRegistrationService().load(newNameTypeDesignationTarget.getUuid(), Arrays.asList("typeDesignations"));
695
                registration.getTypeDesignations().add(nameTypeDesignation);
696
                session.merge(registration);
697
                txstate.commit();
698
                session.close();
699

    
700
                refreshView(true);
701
            } else if(event.getReason().equals(Reason.CANCEL)){
702
                // noting to do
703
            }
704
            newNameTypeDesignationTarget = null;
705
        }
706
        // ignore other editors
707
    }
708

    
709

    
710
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationWorkingSet.class)
711
    public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent<RegistrationWorkingSet,?> event) {
712

    
713
        if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
714
            List<String> messages = new ArrayList<>();
715
            for(RegistrationDTO dto : workingset.getRegistrationDTOs()){
716
                dto.getValidationProblems().forEach(m -> messages.add(dto.getSummary() + ": " + m));
717
            }
718
            getView().openDetailsPopup("Validation Problems", messages);
719
        }
720
    }
721

    
722
    @EventBusListenerMethod
723
    public void onEntityChangeEvent(EntityChangeEvent event){
724

    
725
        if(workingset == null){
726
            return;
727
        }
728
        if(Reference.class.isAssignableFrom(event.getEntityType())){
729
            if(workingset.getCitationUuid().equals(event.getEntityUuid())){
730
                refreshView(true);
731
            }
732
        } else
733
        if(Registration.class.isAssignableFrom(event.getEntityType())){
734
            if(workingset.getRegistrations().stream().anyMatch(reg -> reg.getUuid() == event.getEntityUuid())){
735
                refreshView(true);
736
            }
737
        } else
738
        if(TaxonName.class.isAssignableFrom(event.getEntityType()) && isFromOwnView(event)){
739
            if(event.getType().equals(EntityChangeEvent.Type.CREATED)){
740
                // new name! create a blocking registration
741
                Stack<EditorActionContext>context = ((AbstractPopupEditor)event.getSourceView()).getEditorActionContext();
742
                EditorActionContext rootContext = context.get(0);
743
                if(rootContext.getParentView().equals(getView())){
744
                    Registration blockingRegistration = createNewRegistrationForName(event.getEntityUuid());
745
                    TypedEntityReference<Registration> regReference = (TypedEntityReference<Registration>)rootContext.getParentEntity();
746
                    Registration registration = getRepo().getRegistrationService().load(regReference.getUuid(), REGISTRATION_INIT_STRATEGY);
747
                    registration.getBlockedBy().add(blockingRegistration);
748
                    getRepo().getRegistrationService().saveOrUpdate(registration);
749
                    logger.debug("Blocking registration created");
750
                } else {
751
                    logger.debug("Non blocking registration, since a new name for a new registration has been created");
752
                }
753
            }
754
            if(workingset.getRegistrationDTOs().stream().anyMatch(reg ->
755
                reg.getTypifiedNameRef() != null
756
                && reg.getTypifiedNameRef().getUuid().equals(event.getEntityUuid()))){
757
                    refreshView(true);
758
            }
759
        } else
760
        if(TypeDesignationBase.class.isAssignableFrom(event.getEntityType())){
761
            if(workingset.getRegistrationDTOs().stream().anyMatch(
762
                    reg -> reg.typeDesignations() != null && reg.typeDesignations().stream().anyMatch(
763
                            td -> td.getUuid() == event.getEntityUuid()
764
                            )
765
                        )
766
                    ){
767
                refreshView(true);
768
            }
769
        }
770
    }
771

    
772

    
773
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationDTO.class)
774
    public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent<RegistrationDTO, UUID> event) {
775

    
776
        // FIXME check from own view!!!
777
        if(getView() == null){
778
            return;
779
        }
780

    
781
        UUID registrationUuid = event.getIdentifier();
782

    
783
        RegistrationDTO regDto = getWorkingSetService().loadDtoByUuid(registrationUuid);
784
        if(event.getProperty().equals(RegistrationItem.BLOCKED_BY)){
785

    
786
            Set<RegistrationDTO> blockingRegs = getWorkingSetService().loadBlockingRegistrations(registrationUuid);
787
            getView().setBlockingRegistrations(registrationUuid, blockingRegs);
788
        } else if(event.getProperty().equals(RegistrationItem.MESSAGES)){
789

    
790
            RegistrationMessagesPopup popup = openPopupEditor(RegistrationMessagesPopup.class, null);
791
            popup.loadMessagesFor(regDto.getUuid());
792

    
793
        } else if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
794
            getView().openDetailsPopup("Validation Problems", regDto.getValidationProblems());
795
        }
796

    
797

    
798
    }
799

    
800
}
(13-13/20)