Project

General

Profile

Download (37.2 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
     * Checks
176
     * <ol>
177
     * <li>if there is any registration for this name created in the current registration system</li>
178
     * <li>Checks if the name belongs to the current workingset</li>
179
     * </ol>
180
     * If both checks are successful the method returns <code>true</code>.
181
     */
182
    public boolean canCreateRegistrationForName(TaxonName name) {
183
        for(Registration reg : name.getRegistrations()){
184
            if(minter.isFromOwnRegistration(reg.getIdentifier())){
185
                return false;
186
            }
187
        }
188
        Reference nomRef = name.getNomenclaturalReference();
189
        UUID citationUuid = workingset.getCitationUuid();
190
        // @formatter:off
191
        return nomRef != null && (
192
                // nomref matches
193
                nomRef.getUuid().equals(citationUuid) ||
194
                // nomref.inreference matches
195
                (nomRef.getType() != null && nomRef.getType() == ReferenceType.Section && nomRef.getInReference() != null && nomRef.getInReference().getUuid().equals(citationUuid))
196
                );
197
        // @formatter:on
198
    }
199

    
200

    
201
    /**
202
     * @param taxonNameId
203
     * @return
204
     */
205
    protected Registration createNewRegistrationForName(UUID taxonNameUuid) {
206
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207
        // move into RegistrationWorkflowStateMachine
208
        TransactionStatus txStatus = getRepo().startTransaction();
209

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

    
228
    /**
229
     * @param doReload TODO
230
     *
231
     */
232
    protected void refreshView(boolean doReload) {
233
        if(workingset == null){
234
            return; // nothing to do
235
        }
236
        if(doReload){
237
            loadWorkingSet(workingset.getCitationUuid());
238
        }
239
        applyWorkingset();
240
    }
241

    
242
    /**
243
     * {@inheritDoc}
244
     */
245
    @Override
246
    public void handleViewEntered() {
247
        super.handleViewEntered();
248
        // TODO currently cannot specify type more precisely, see AbstractSelect
249
        // FIXME externalize into class file!!!!!!!!!!!!
250
        getView().setStatusComponentInstantiator(new RegistrationStatusFieldInstantiator<Object>(){
251

    
252
            private static final long serialVersionUID = 7099181280977511048L;
253

    
254
            @Override
255
            public AbstractField<Object> create(RegistrationDTO regDto) {
256

    
257
                CdmBeanItemContainerFactory selectFieldFactory = new CdmBeanItemContainerFactory(getRepo());
258
                // submitters have GrantedAuthorities like REGISTRATION(PREPARATION).[UPDATE]{ab4459eb-3b96-40ba-bfaa-36915107d59e}
259
                UserHelper userHelper = UserHelperAccess.userHelper();
260
                Set<RegistrationStatus> availableStatus = new HashSet<>();
261

    
262
                boolean canChangeStatus = userHelper.userHasPermission(regDto.registration(), CRUD.UPDATE);
263
                availableStatus.add(regDto.getStatus());
264
                if(canChangeStatus){
265
                    if(userHelper.userIsAdmin()){
266
                        availableStatus.addAll(Arrays.asList(RegistrationStatus.values()));
267
                    } else {
268
                        availableStatus.addAll(RegistrationStatusTransitions.possibleTransitions(regDto.getStatus()));
269
                    }
270
                }
271

    
272
                RegistrationStatusSelect select = new RegistrationStatusSelect(null, selectFieldFactory.buildBeanItemContainer(
273
                        RegistrationStatus.class,
274
                        availableStatus.toArray(new RegistrationStatus[availableStatus.size()]))
275
                        );
276
                select.addValueChangeListener(e -> saveRegistrationStatusChange(regDto.getUuid(), e.getProperty().getValue()));
277
                select.setEnabled(canChangeStatus);
278
                select.setNullSelectionAllowed(false);
279
                return select;
280
            }
281

    
282

    
283
        });
284
        loadWorkingSet(getView().getCitationUuid());
285
        applyWorkingset();
286

    
287
    }
288

    
289
    private void applyWorkingset(){
290
         getView().setWorkingset(workingset);
291
        // PagingProviders and CacheGenerator for the existingNameCombobox
292
        activateComboboxes();
293
        // update the messages
294
        updateMessages();
295
    }
296

    
297
    /**
298
     *
299
     */
300
    protected void activateComboboxes() {
301
        CdmFilterablePagingProvider<TaxonName, TaxonName> pagingProvider = new CdmFilterablePagingProvider<TaxonName, TaxonName>(
302
                getRepo().getNameService());
303
        pagingProvider.setInitStrategy(Arrays.asList("registrations", "nomenclaturalReference"));
304
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenerator = new CdmTitleCacheCaptionGenerator<TaxonName>();
305
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenerator);
306
        getView().getAddExistingNameCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
307
    }
308

    
309
    /**
310
     *
311
     */
312
    protected void updateMessages() {
313
        User user = UserHelperAccess.userHelper().user();
314
        for (UUID registrationUuid : getView().getRegistrationItemMap().keySet()) {
315
            Button messageButton = getView().getRegistrationItemMap().get(registrationUuid).regItemButtons.getMessagesButton();
316

    
317
            RegistrationDTO regDto = workingset.getRegistrationDTO(registrationUuid).get();
318
            try {
319
                int messageCount = messageService.countActiveMessagesFor(regDto.registration(), user);
320

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

    
341
                }
342
            } catch (ExternalServiceException e) {
343
                messageButton.setComponentError(new SystemError(e.getMessage(), e));
344
            }
345
        }
346
    }
347

    
348

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

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

    
385

    
386
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
387
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
388

    
389
        if(!checkFromOwnView(event)){
390
            return;
391
        }
392

    
393
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
394
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
395
        popup.loadInEditor(null);
396
    }
397

    
398
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
399
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
400

    
401
        if(!checkFromOwnView(event)){
402
            return;
403
        }
404
        ReferencePopupEditor popup = openPopupEditor(ReferencePopupEditor.class, event);
405
        popup.withReferenceTypes(RegistrationUIDefaults.PRINTPUB_REFERENCE_TYPES);
406
        popup.withDeleteButton(true);
407
        popup.loadInEditor(event.getEntityUuid());
408
    }
409

    
410
    @EventBusListenerMethod
411
    public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
412
        if(event.getPopup() instanceof ReferencePopupEditor){
413
            if(event.getReason().equals(Reason.SAVE)){
414
                refreshView(true);
415
            }
416
        }
417
    }
418

    
419
    @EventBusListenerMethod
420
    public void onDoneWithSpecimenTypeDesignationWorkingsetPopupEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
421
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
422
            if(event.getReason().equals(Reason.SAVE)){
423
                refreshView(true);
424
            }
425
        }
426
    }
427

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

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

    
435
        RegistrationPopupEditor popup = openPopupEditor(RegistrationPopupEditor.class, event);
436
        popup.loadInEditor(event.getEntityUuid());
437
    }
438

    
439
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
440
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
441

    
442
        if(!checkFromOwnView(event)){
443
            return;
444
        }
445

    
446
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
447
        popup.setParentEditorActionContext(event.getContext());
448
        popup.withDeleteButton(true);
449
        configureTaxonNameEditor(popup);
450
        popup.loadInEditor(event.getEntityUuid());
451
        if(event.hasSource() && event.getSource().isReadOnly()){
452
            // avoid resetting readonly to false
453
            popup.setReadOnly(true);
454
        }
455

    
456
    }
457

    
458

    
459
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
460
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
461

    
462
        if(!checkFromOwnView(event)){
463
            return;
464
        }
465

    
466
        newTaxonNameForRegistration = TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
467
        newTaxonNameForRegistration.setNomenclaturalReference(getRepo().getReferenceService().find(workingset.getCitationUuid()));
468
        EntityChangeEvent nameSaveEvent = getTaxonNameStore().saveBean(newTaxonNameForRegistration, (AbstractView) getView());
469
        newTaxonNameForRegistration = getRepo().getNameService().find(nameSaveEvent.getEntityUuid());
470
        TaxonNamePopupEditor popup = openPopupEditor(TaxonNamePopupEditor.class, event);
471
        popup.setParentEditorActionContext(event.getContext());
472
        popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE,CRUD.DELETE));
473
        popup.withDeleteButton(true);
474
        configureTaxonNameEditor(popup);
475
        popup.loadInEditor(newTaxonNameForRegistration.getUuid());
476
    }
477

    
478
    /**
479
     * TODO consider putting this into a Configurer Bean per UIScope.
480
     * In the configurator bean this methods popup papamerter should be of the type
481
     * AbstractPopupEditor
482
     *
483
     * @param popup
484
     */
485
    protected void configureTaxonNameEditor(TaxonNamePopupEditorView popup) {
486
        popup.enableMode(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA);
487
        popup.enableMode(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
488
        popup.enableMode(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART);
489
        // popup.enableMode(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE);
490
    }
491

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

    
528

    
529
    /**
530
     * Creates a new Registration for an exiting (previously published name).
531
     *
532
     * @param event
533
     * @throws RegistrationValidationException
534
     */
535
    @EventBusListenerMethod
536
    public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event) throws RegistrationValidationException {
537

    
538
        if(!event.isStart()){
539
            return;
540
        }
541

    
542
        getView().getAddExistingNameCombobox().commit(); // update the chosen value in the datasource
543
        TaxonName typifiedName = getView().getAddExistingNameCombobox().getValue();
544
        if(typifiedName != null){
545
            boolean reloadWorkingSet = false;
546
            Reference citation = getRepo().getReferenceService().find(workingset.getCitationUuid());
547
            // here we completely ignore the ExistingNameRegistrationType since the user should not have the choice
548
            // to create a typification only registration in the working (publication) set which contains
549
            // the protologe. This is known from the nomenclatural reference.
550
            if(canCreateRegistrationForName(typifiedName)){
551
                // the citation which is the base for workingset contains the protologe of the name and the name hast not
552
                // been registered before:
553
                // create a registration for the name and the first typifications
554
                Registration newRegistrationWithExistingName = createNewRegistrationForName(typifiedName.getUuid());
555
                newRegistrationDTOWithExistingName = new RegistrationDTO(newRegistrationWithExistingName, typifiedName, citation);
556
                reloadWorkingSet = true;
557
            } else {
558
                // create a typification only registration
559
                // FIXME: this should not be possible if the names protologue is in the workingset --> #
560
                Registration newRegistrationWithExistingName = createNewRegistrationForName(null);
561
                newRegistrationDTOWithExistingName = new RegistrationDTO(newRegistrationWithExistingName, typifiedName, citation);
562
            }
563
            workingset.add(newRegistrationDTOWithExistingName);
564
            // tell the view to update the workingset
565
            refreshView(reloadWorkingSet);
566
            getView().getAddExistingNameRegistrationButton().setEnabled(false);
567
            if(newRegistrationDTOWithExistingName.registration().getName() == null){
568
                getView().getAddExistingNameCombobox().setEnabled(false);
569
                getView().getAddNewNameRegistrationButton().setEnabled(false);
570
                getView().getAddNewNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
571
                getView().getAddExistingNameCombobox().setDescription("You first need to add a type designation to the previously created registration.");
572
                getView().getAddExistingNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
573
            }
574
        } else {
575
            logger.error("Seletced name is NULL");
576
        }
577

    
578
    }
579

    
580

    
581
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
582
    public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event) {
583

    
584
        if(!checkFromOwnView(event)){
585
            return;
586
        }
587

    
588
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET ){
589
            SpecimenTypeDesignationWorkingsetPopupEditor popup = openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor.class, event);
590
            popup.setParentEditorActionContext(event.getContext());
591
            popup.withDeleteButton(true);
592
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
593
            if(event.hasSource()){
594
                // propagate readonly state from source button to popup
595
                popup.setReadOnly(event.getSource().isReadOnly());
596
            }
597
        } else {
598
            NameTypeDesignationPopupEditor popup = openPopupEditor(NameTypeDesignationPopupEditor.class, event);
599
            popup.setParentEditorActionContext(event.getContext());
600
            popup.withDeleteButton(true);
601
            popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationUuid(), event.getBaseEntityRef()));
602

    
603
            popup.getCitationCombobox().setEnabled(false);
604
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
605

    
606
            if(event.hasSource()){
607
                // propagate readonly state from source button to popup
608
                popup.setReadOnly(event.getSource().isReadOnly());
609
            }
610
            newNameTypeDesignationTarget = workingset.getRegistrationDTO(event.getRegistrationUuid()).get();
611
        }
612
    }
613

    
614
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
615
    public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event) {
616

    
617
        if(!event.hasSource()){
618
            return;
619
        }
620

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

    
659
                @Override
660
                public NameTypeDesignation createNewBean() {
661

    
662
                    TaxonName typifiedName = getRepo().getNameService().load(event.getTypifiedNameUuid(), Arrays.asList(new String[]{"typeDesignations", "homotypicalGroup"}));
663
                    NameTypeDesignation nameTypeDesignation  = NameTypeDesignation.NewInstance();
664
                    nameTypeDesignation.setCitation(newNameTypeDesignationTarget.getCitation());
665
                    nameTypeDesignation.getTypifiedNames().add(typifiedName);
666
                    return nameTypeDesignation;
667
                }
668
            });
669
            popup.loadInEditor(null);
670
            popup.getCitationCombobox().setEnabled(false);
671
            popup.getTypifiedNamesComboboxSelect().setEnabled(false);
672
            if(event.hasSource()){
673
                // propagate readonly state from source component to popup
674
                popup.setReadOnly(event.getSource().isReadOnly());
675
            }
676
        }
677
    }
678

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

    
705
                Session session = getRepo().getSessionFactory().openSession();
706
                Transaction txstate = session.beginTransaction();
707
                TypeDesignationBase<?> nameTypeDesignation = getRepo().getNameService().loadTypeDesignation(uuid, Arrays.asList(""));
708
                // only load the typeDesignations with the registration so that the typified name can  not be twice in the session
709
                // otherwise multiple representation problems might occur
710
                Registration registration = getRepo().getRegistrationService().load(newNameTypeDesignationTarget.getUuid(), Arrays.asList("typeDesignations"));
711
                registration.getTypeDesignations().add(nameTypeDesignation);
712
                session.merge(registration);
713
                txstate.commit();
714
                session.close();
715

    
716
                refreshView(true);
717
            } else if(event.getReason().equals(Reason.CANCEL)){
718
                // noting to do
719
            }
720
            newNameTypeDesignationTarget = null;
721
        }
722
        // ignore other editors
723
    }
724

    
725

    
726
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationWorkingSet.class)
727
    public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent<RegistrationWorkingSet,?> event) {
728

    
729
        if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
730
            List<String> messages = new ArrayList<>();
731
            for(RegistrationDTO dto : workingset.getRegistrationDTOs()){
732
                dto.getValidationProblems().forEach(m -> messages.add(dto.getSummary() + ": " + m));
733
            }
734
            getView().openDetailsPopup("Validation Problems", messages);
735
        }
736
    }
737

    
738
    @EventBusListenerMethod
739
    public void onEntityChangeEvent(EntityChangeEvent event){
740

    
741
        if(workingset == null){
742
            return;
743
        }
744
        if(Reference.class.isAssignableFrom(event.getEntityType())){
745

    
746
            if(workingset.getCitationUuid().equals(event.getEntityUuid())){
747
                if(event.isRemovedType()){
748
                    viewEventBus.publish(EventScope.UI, this, new NavigationEvent(StartRegistrationViewBean.NAME));
749
                } else {
750
                    refreshView(true);
751
                }
752
            }
753

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

    
794

    
795
    @EventBusListenerMethod(filter = ShowDetailsEventEntityTypeFilter.RegistrationDTO.class)
796
    public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent<RegistrationDTO, UUID> event) {
797

    
798
        // FIXME check from own view!!!
799
        if(getView() == null){
800
            return;
801
        }
802

    
803
        UUID registrationUuid = event.getIdentifier();
804

    
805
        RegistrationDTO regDto = getWorkingSetService().loadDtoByUuid(registrationUuid);
806
        if(event.getProperty().equals(RegistrationItem.BLOCKED_BY)){
807

    
808
            Set<RegistrationDTO> blockingRegs = getWorkingSetService().loadBlockingRegistrations(registrationUuid);
809
            getView().setBlockingRegistrations(registrationUuid, blockingRegs);
810
        } else if(event.getProperty().equals(RegistrationItem.MESSAGES)){
811

    
812
            RegistrationMessagesPopup popup = openPopupEditor(RegistrationMessagesPopup.class, null);
813
            popup.loadMessagesFor(regDto.getUuid());
814

    
815
        } else if(event.getProperty().equals(RegistrationItem.VALIDATION_PROBLEMS)){
816
            getView().openDetailsPopup("Validation Problems", regDto.getValidationProblems());
817
        }
818

    
819

    
820
    }
821

    
822
}
(13-13/20)