Project

General

Profile

Download (36.5 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.EventScope;
28
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
29

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

    
40
import eu.etaxonomy.cdm.api.service.INameService;
41
import eu.etaxonomy.cdm.api.service.IRegistrationService;
42
import eu.etaxonomy.cdm.api.service.config.RegistrationStatusTransitions;
43
import eu.etaxonomy.cdm.api.service.dto.RegistrationDTO;
44
import eu.etaxonomy.cdm.api.service.dto.RegistrationWorkingSet;
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.api.service.registration.IRegistrationWorkingSetService;
50
import eu.etaxonomy.cdm.api.utility.UserHelper;
51
import eu.etaxonomy.cdm.ext.common.ExternalServiceException;
52
import eu.etaxonomy.cdm.ext.registration.messages.IRegistrationMessageService;
53
import eu.etaxonomy.cdm.model.common.User;
54
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
55
import eu.etaxonomy.cdm.model.name.Rank;
56
import eu.etaxonomy.cdm.model.name.Registration;
57
import eu.etaxonomy.cdm.model.name.RegistrationStatus;
58
import eu.etaxonomy.cdm.model.name.TaxonName;
59
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
60
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
61
import eu.etaxonomy.cdm.model.reference.Reference;
62
import eu.etaxonomy.cdm.model.reference.ReferenceType;
63
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
64
import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;
65
import eu.etaxonomy.cdm.ref.EntityReference;
66
import eu.etaxonomy.cdm.ref.TypedEntityReference;
67
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
68
import eu.etaxonomy.cdm.service.CdmStore;
69
import eu.etaxonomy.cdm.service.UserHelperAccess;
70
import eu.etaxonomy.cdm.vaadin.component.CdmBeanItemContainerFactory;
71
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationItem;
72
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStatusFieldInstantiator;
73
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStatusSelect;
74
import eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.EditorActionContext;
75
import eu.etaxonomy.cdm.vaadin.event.EditorActionTypeFilter;
76
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
77
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
78
import eu.etaxonomy.cdm.vaadin.event.RegistrationEditorAction;
79
import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEvent;
80
import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEventEntityTypeFilter;
81
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
82
import eu.etaxonomy.cdm.vaadin.event.TypeDesignationWorkingsetEditorAction;
83
import eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkingsetAction;
84
import eu.etaxonomy.cdm.vaadin.permission.RegistrationCuratorRoleProbe;
85
import eu.etaxonomy.cdm.vaadin.theme.EditValoTheme;
86
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
87
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
88
import eu.etaxonomy.cdm.vaadin.view.name.NameTypeDesignationPopupEditor;
89
import eu.etaxonomy.cdm.vaadin.view.name.SpecimenTypeDesignationWorkingsetPopupEditor;
90
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditor;
91
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditorMode;
92
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditorView;
93
import eu.etaxonomy.cdm.vaadin.view.name.TypeDesignationWorkingsetEditorIdSet;
94
import eu.etaxonomy.cdm.vaadin.view.reference.ReferencePopupEditor;
95
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
96
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
97
import eu.etaxonomy.vaadin.mvp.AbstractView;
98
import eu.etaxonomy.vaadin.mvp.BeanInstantiator;
99
import eu.etaxonomy.vaadin.ui.navigation.NavigationEvent;
100
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
101
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent.Reason;
102

    
103
/**
104
 * @author a.kohlbecker
105
 * @since Mar 3, 2017
106
 *
107
 */
108
@SpringComponent
109
@ViewScope
110
public class RegistrationWorkingsetPresenter extends AbstractPresenter<RegistrationWorkingsetView> {
111

    
112
    private static final Logger logger = Logger.getLogger(RegistrationWorkingsetPresenter.class);
113

    
114
    private static final List<String> REGISTRATION_INIT_STRATEGY = Arrays.asList(
115
            "$",
116
            "blockedBy",
117
            "name.combinationAuthorship",
118
            "name.exCombinationAuthorship",
119
            "name.basionymAuthorship",
120
            "name.exBasionymAuthorship"
121
            );
122

    
123
    private static final long serialVersionUID = 1L;
124

    
125
    @Autowired
126
    private IRegistrationWorkingSetService regWorkingSetService;
127

    
128
    @Autowired
129
    private RegistrationIdentifierMinter minter;
130

    
131
    @Autowired
132
    private IRegistrationMessageService messageService;
133

    
134
    /**
135
     * @return the regWorkingSetService
136
     */
137
    public IRegistrationWorkingSetService getWorkingSetService() {
138
        return regWorkingSetService;
139
    }
140

    
141
    private RegistrationWorkingSet workingset;
142

    
143
    private TaxonName newTaxonNameForRegistration = null;
144

    
145
    private RegistrationDTO newRegistrationDTOWithExistingName;
146

    
147
    private RegistrationDTO newNameTypeDesignationTarget;
148

    
149

    
150
    /**
151
     *
152
     */
153
    public RegistrationWorkingsetPresenter() {
154
    }
155

    
156
    /**
157
     * Always create a new Store
158
     *
159
     * @return
160
     */
161
    protected CdmStore<Registration, IRegistrationService> getRegistrationStore(){
162
        return new CdmStore<Registration, IRegistrationService>(getRepo(), getRepo().getRegistrationService());
163
    }
164

    
165
    /**
166
     * Always create a new Store
167
     *
168
     * @return
169
     */
170
    protected CdmStore<TaxonName, INameService> getTaxonNameStore(){
171
        return new  CdmStore<TaxonName, INameService>(getRepo(), getRepo().getNameService());
172
    }
173

    
174

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

    
193

    
194
    /**
195
     * @param taxonNameId
196
     * @return
197
     */
198
    protected Registration createNewRegistrationForName(UUID taxonNameUuid) {
199
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
200
        // move into RegistrationWorkflowStateMachine
201
        TransactionStatus txStatus = getRepo().startTransaction();
202

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

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

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

    
245
            private static final long serialVersionUID = 7099181280977511048L;
246

    
247
            @Override
248
            public AbstractField<Object> create(RegistrationDTO regDto) {
249

    
250
                CdmBeanItemContainerFactory selectFieldFactory = new CdmBeanItemContainerFactory(getRepo());
251
                // submitters have GrantedAuthorities like REGISTRATION(PREPARATION).[UPDATE]{ab4459eb-3b96-40ba-bfaa-36915107d59e}
252
                UserHelper userHelper = UserHelperAccess.userHelper();
253
                Set<RegistrationStatus> availableStatus = new HashSet<>();
254

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

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

    
275

    
276
        });
277
        loadWorkingSet(getView().getCitationUuid());
278
        applyWorkingset();
279

    
280
    }
281

    
282
    private void applyWorkingset(){
283
         getView().setWorkingset(workingset);
284
        // PagingProviders and CacheGenerator for the existingNameCombobox
285
        activateComboboxes();
286
        // update the messages
287
        updateMessages();
288
    }
289

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

    
302
    /**
303
     *
304
     */
305
    protected void updateMessages() {
306
        User user = UserHelperAccess.userHelper().user();
307
        for (UUID registrationUuid : getView().getRegistrationItemMap().keySet()) {
308
            Button messageButton = getView().getRegistrationItemMap().get(registrationUuid).regItemButtons.getMessagesButton();
309

    
310
            RegistrationDTO regDto = workingset.getRegistrationDTO(registrationUuid).get();
311
            try {
312
                int messageCount = messageService.countActiveMessagesFor(regDto.registration(), user);
313

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

    
334
                }
335
            } catch (ExternalServiceException e) {
336
                messageButton.setComponentError(new SystemError(e.getMessage(), e));
337
            }
338
        }
339
    }
340

    
341

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

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

    
378

    
379
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
380
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
381

    
382
        if(!checkFromOwnView(event)){
383
            return;
384
        }
385

    
386
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
387
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
388
        popup.loadInEditor(null);
389
    }
390

    
391
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
392
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
393

    
394
        if(!checkFromOwnView(event)){
395
            return;
396
        }
397
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
398
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
399
        popup.withDeleteButton(true);
400
        popup.loadInEditor(event.getEntityUuid());
401
    }
402

    
403
    @EventBusListenerMethod
404
    public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
405
        if(event.getPopup() instanceof ReferencePopupEditor){
406
            if(event.getReason().equals(Reason.SAVE)){
407
                refreshView(true);
408
            }
409
        }
410
    }
411

    
412
    @EventBusListenerMethod
413
    public void onDoneWithSpecimenTypeDesignationWorkingsetPopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
414
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
415
            if(event.getReason().equals(Reason.SAVE)){
416
                refreshView(true);
417
            }
418
        }
419
    }
420

    
421
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
422
    public void onRegistrationEditorAction(RegistrationEditorAction event) {
423

    
424
        if(!checkFromOwnView(event)){
425
            return;
426
        }
427

    
428
        RegistrationPopupEditor popup = openPopupEditor(RegistrationPopupEditor.class, event);
429
        popup.loadInEditor(event.getEntityUuid());
430
    }
431

    
432
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
433
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
434

    
435
        if(!checkFromOwnView(event)){
436
            return;
437
        }
438

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

    
449
    }
450

    
451

    
452
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
453
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
454

    
455
        if(!checkFromOwnView(event)){
456
            return;
457
        }
458

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

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

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

    
521

    
522
    /**
523
     * Creates a new Registration for an exiting (previously published name).
524
     *
525
     * @param event
526
     * @throws RegistrationValidationException
527
     */
528
    @EventBusListenerMethod
529
    public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event) throws RegistrationValidationException {
530

    
531
        if(!event.isStart()){
532
            return;
533
        }
534

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

    
566
    }
567

    
568

    
569
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
570
    public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event) {
571

    
572
        if(!checkFromOwnView(event)){
573
            return;
574
        }
575

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

    
591
            popup.getCitationCombobox().setEnabled(false);
592
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
593

    
594
            if(event.hasSource()){
595
                // propagate readonly state from source button to popup
596
                popup.setReadOnly(event.getSource().isReadOnly());
597
            }
598
            newNameTypeDesignationTarget = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
599
        }
600
    }
601

    
602
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
603
    public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event) {
604

    
605
        if(!event.hasSource()){
606
            return;
607
        }
608

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

    
647
                @Override
648
                public NameTypeDesignation createNewBean() {
649

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

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

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

    
704
                refreshView(true);
705
            } else if(event.getReason().equals(Reason.CANCEL)){
706
                // noting to do
707
            }
708
            newNameTypeDesignationTarget = null;
709
        }
710
        // ignore other editors
711
    }
712

    
713

    
714
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationWorkingSet.class)
715
    public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent<RegistrationWorkingSet,?> event) {
716

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

    
726
    @EventBusListenerMethod
727
    public void onEntityChangeEvent(EntityChangeEvent event){
728

    
729
        if(workingset == null){
730
            return;
731
        }
732
        if(Reference.class.isAssignableFrom(event.getEntityType())){
733

    
734
            if(workingset.getCitationUuid().equals(event.getEntityUuid())){
735
                if(event.isRemovedType()){
736
                    viewEventBus.publish(EventScope.UI, this, new NavigationEvent(StartRegistrationViewBean.NAME));
737
                } else {
738
                    refreshView(true);
739
                }
740
            }
741

    
742
        } else
743
        if(Registration.class.isAssignableFrom(event.getEntityType())){
744
            if(workingset.getRegistrations().stream().anyMatch(reg -> reg.getUuid() == event.getEntityUuid())){
745
                refreshView(true);
746
            }
747
        } else
748
        if(TaxonName.class.isAssignableFrom(event.getEntityType()) && isFromOwnView(event)){
749
            if(event.getType().equals(EntityChangeEvent.Type.CREATED)){
750
                // new name! create a blocking registration
751
                Stack<EditorActionContext>context = ((AbstractPopupEditor)event.getSourceView()).getEditorActionContext();
752
                EditorActionContext rootContext = context.get(0);
753
                if(rootContext.getParentView().equals(getView())){
754
                    Registration blockingRegistration = createNewRegistrationForName(event.getEntityUuid());
755
                    TypedEntityReference<Registration> regReference = (TypedEntityReference<Registration>)rootContext.getParentEntity();
756
                    Registration registration = getRepo().getRegistrationService().load(regReference.getUuid(), REGISTRATION_INIT_STRATEGY);
757
                    registration.getBlockedBy().add(blockingRegistration);
758
                    getRepo().getRegistrationService().saveOrUpdate(registration);
759
                    logger.debug("Blocking registration created");
760
                } else {
761
                    logger.debug("Non blocking registration, since a new name for a new registration has been created");
762
                }
763
            }
764
            if(workingset.getRegistrationDTOs().stream().anyMatch(reg ->
765
                reg.getTypifiedNameRef() != null
766
                && reg.getTypifiedNameRef().getUuid().equals(event.getEntityUuid()))){
767
                    refreshView(true);
768
            }
769
        } else
770
        if(TypeDesignationBase.class.isAssignableFrom(event.getEntityType())){
771
            if(workingset.getRegistrationDTOs().stream().anyMatch(
772
                    reg -> reg.typeDesignations() != null && reg.typeDesignations().stream().anyMatch(
773
                            td -> td.getUuid() == event.getEntityUuid()
774
                            )
775
                        )
776
                    ){
777
                refreshView(true);
778
            }
779
        }
780
    }
781

    
782

    
783
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationDTO.class)
784
    public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent<RegistrationDTO, UUID> event) {
785

    
786
        // FIXME check from own view!!!
787
        if(getView() == null){
788
            return;
789
        }
790

    
791
        UUID registrationUuid = event.getIdentifier();
792

    
793
        RegistrationDTO regDto = getWorkingSetService().loadDtoByUuid(registrationUuid);
794
        if(event.getProperty().equals(RegistrationItem.BLOCKED_BY)){
795

    
796
            Set<RegistrationDTO> blockingRegs = getWorkingSetService().loadBlockingRegistrations(registrationUuid);
797
            getView().setBlockingRegistrations(registrationUuid, blockingRegs);
798
        } else if(event.getProperty().equals(RegistrationItem.MESSAGES)){
799

    
800
            RegistrationMessagesPopup popup = openPopupEditor(RegistrationMessagesPopup.class, null);
801
            popup.loadMessagesFor(regDto.getUuid());
802

    
803
        } else if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
804
            getView().openDetailsPopup("Validation Problems", regDto.getValidationProblems());
805
        }
806

    
807

    
808
    }
809

    
810
}
(13-13/20)