Project

General

Profile

Download (19.3 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.EnumSet;
13
import java.util.List;
14

    
15
import org.springframework.beans.factory.annotation.Autowired;
16
import org.springframework.context.event.EventListener;
17
import org.springframework.security.core.Authentication;
18

    
19
import com.vaadin.spring.annotation.SpringComponent;
20
import com.vaadin.spring.annotation.ViewScope;
21
import com.vaadin.ui.Label;
22
import com.vaadin.ui.UI;
23
import com.vaadin.ui.VerticalLayout;
24
import com.vaadin.ui.Window;
25

    
26
import eu.etaxonomy.cdm.api.service.INameService;
27
import eu.etaxonomy.cdm.api.service.IRegistrationService;
28
import eu.etaxonomy.cdm.model.common.User;
29
import eu.etaxonomy.cdm.model.name.Rank;
30
import eu.etaxonomy.cdm.model.name.Registration;
31
import eu.etaxonomy.cdm.model.name.RegistrationStatus;
32
import eu.etaxonomy.cdm.model.name.TaxonName;
33
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
34
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
35
import eu.etaxonomy.cdm.model.reference.Reference;
36
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
37
import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;
38
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
39
import eu.etaxonomy.cdm.service.CdmStore;
40
import eu.etaxonomy.cdm.service.IRegistrationWorkingSetService;
41
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
42
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
43
import eu.etaxonomy.cdm.vaadin.event.RegistrationEditorAction;
44
import eu.etaxonomy.cdm.vaadin.event.ShowDetailsEvent;
45
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
46
import eu.etaxonomy.cdm.vaadin.event.TypeDesignationWorkingsetEditorAction;
47
import eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkingsetAction;
48
import eu.etaxonomy.cdm.vaadin.model.EntityReference;
49
import eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet;
50
import eu.etaxonomy.cdm.vaadin.security.UserHelper;
51
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
52
import eu.etaxonomy.cdm.vaadin.util.converter.TypeDesignationSetManager.TypeDesignationWorkingSetType;
53
import eu.etaxonomy.cdm.vaadin.view.name.SpecimenTypeDesignationWorkingsetPopupEditor;
54
import eu.etaxonomy.cdm.vaadin.view.name.TaxonNamePopupEditor;
55
import eu.etaxonomy.cdm.vaadin.view.name.TypeDesignationWorkingsetEditorIdSet;
56
import eu.etaxonomy.cdm.vaadin.view.reference.ReferencePopupEditor;
57
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
58
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
59
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent.Reason;
60

    
61
/**
62
 * @author a.kohlbecker
63
 * @since Mar 3, 2017
64
 *
65
 */
66
@SpringComponent
67
@ViewScope
68
public class RegistrationWorkingsetPresenter extends AbstractPresenter<RegistrationWorkingsetView> {
69

    
70
    private static final long serialVersionUID = 1L;
71

    
72
    @Autowired
73
    private IRegistrationWorkingSetService workingSetService;
74

    
75
    /**
76
     * @return the workingSetService
77
     */
78
    public IRegistrationWorkingSetService getWorkingSetService() {
79
        ensureBoundConversation();
80
        return workingSetService;
81
    }
82

    
83
    private RegistrationWorkingSet workingset;
84

    
85
    private TaxonName newTaxonNameForRegistration = null;
86

    
87
    private RegistrationDTO newRegistrationDTOWithExistingName;
88

    
89

    
90
    /**
91
     *
92
     */
93
    public RegistrationWorkingsetPresenter() {
94
    }
95

    
96

    
97
    /**
98
     * Always create a new Store
99
     *
100
     * @return
101
     */
102
    protected CdmStore<Registration, IRegistrationService> getRegistrationStore(){
103
        return new CdmStore<Registration, IRegistrationService>(getRepo(), getRepo().getRegistrationService());
104
    }
105

    
106
    /**
107
     * Always create a new Store
108
     *
109
     * @return
110
     */
111
    protected CdmStore<TaxonName, INameService> getTaxonNameStore(){
112
        return new  CdmStore<TaxonName, INameService>(getRepo(), getRepo().getNameService());
113
    }
114

    
115

    
116
    /**
117
     * @param taxonNameId
118
     * @return
119
     */
120
    protected Registration createNewRegistrationForName(Integer taxonNameId) {
121
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
122
        // move into RegistrationWorkflowStateMachine
123
        long identifier = System.currentTimeMillis();
124
        Registration reg = Registration.NewInstance(
125
                "http://phycobank.org/" + identifier,
126
                "" + identifier,
127
                taxonNameId != null ? getRepo().getNameService().find(taxonNameId) : null,
128
                null);
129
        Authentication authentication = currentSecurityContext().getAuthentication();
130
        reg.setSubmitter((User)authentication.getPrincipal());
131
        EntityChangeEvent event = getRegistrationStore().saveBean(reg);
132
        UserHelper.fromSession().createAuthorityForCurrentUser(Registration.class, event.getEntityId(), Operation.UPDATE, RegistrationStatus.PREPARATION.name());
133
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134
        return getRepo().getRegistrationService().find(event.getEntityId());
135
    }
136

    
137

    
138
    /**
139
     *
140
     */
141
    protected void refreshView() {
142
        getConversationHolder().getSession().clear();
143
        presentWorkingSet(workingset.getCitationId());
144
    }
145

    
146

    
147
    /**
148
     * {@inheritDoc}
149
     */
150
    @Override
151
    public void handleViewEntered() {
152

    
153
        super.handleViewEntered();
154

    
155
        presentWorkingSet(getView().getCitationID());
156

    
157
        CdmFilterablePagingProvider<TaxonName> pagingProvider = new CdmFilterablePagingProvider<TaxonName>(
158
                getRepo().getNameService(), this);
159
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenrator = new CdmTitleCacheCaptionGenerator<TaxonName>();
160
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenrator);
161
        getView().getAddExistingNameCombobox().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
162
    }
163

    
164
    /**
165
     * Loads the WorkingSet from the data base and passes it to the view.
166
     *
167
     * @param registrationID
168
     */
169
    private void presentWorkingSet(Integer referenceID) {
170
        try {
171
            workingset = getWorkingSetService().loadWorkingSetByReferenceID(referenceID);
172
        } catch (RegistrationValidationException error) {
173
            logger.error(error);
174
            Window errorDialog = new Window("Validation Error");
175
            errorDialog.setModal(true);
176
            VerticalLayout subContent = new VerticalLayout();
177
            subContent.setMargin(true);
178
            errorDialog.setContent(subContent);
179
            subContent.addComponent(new Label(error.getMessage()));
180
            UI.getCurrent().addWindow(errorDialog);
181
        }
182
        if(workingset == null || workingset.getCitationId() == null){
183
            Reference citation = getRepo().getReferenceService().find(referenceID);
184
            workingset = new RegistrationWorkingSet(citation);
185
        }
186
        // getView().setHeaderText("Registrations for " + workingset.getCitation());
187
        getView().setWorkingset(workingset);
188
    }
189

    
190
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).ADD && #event.sourceComponent == null")
191
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
192
        ReferencePopupEditor popup = getNavigationManager().showInPopup(ReferencePopupEditor.class);
193
        popup.loadInEditor(null);
194
    }
195

    
196
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
197
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
198
        ReferencePopupEditor popup = getNavigationManager().showInPopup(ReferencePopupEditor.class);
199
        popup.withDeleteButton(true);
200
        popup.loadInEditor(event.getEntityId());
201
    }
202

    
203
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
204
    public void onRegistrationEditorAction(RegistrationEditorAction event) {
205
        RegistrationPopupEditor popup = getNavigationManager().showInPopup(RegistrationPopupEditor.class);
206
        popup.loadInEditor(event.getEntityId());
207
    }
208

    
209
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
210
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
211

    
212
        TaxonNamePopupEditor popup = getNavigationManager().showInPopup(TaxonNamePopupEditor.class);
213
        popup.withDeleteButton(true);
214
        // disable NomReferenceCombobox:
215
        // the in the registration application inReferences should only edited centrally
216
        popup.getNomReferenceCombobox().setEnabled(false);
217
        popup.loadInEditor(event.getEntityId());
218
    }
219

    
220
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).ADD")
221
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
222

    
223
        newTaxonNameForRegistration = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES());
224
        newTaxonNameForRegistration.setNomenclaturalReference(getRepo().getReferenceService().find(workingset.getCitationId()));
225
        EntityChangeEvent nameSaveEvent = getTaxonNameStore().saveBean(newTaxonNameForRegistration);
226
       // UserHelper.fromSession().createAuthorityForCurrentUser(TaxonName.class, nameSaveEvent.getEntityId(), EnumSet.of(CRUD.UPDATE,CRUD.DELETE), null);
227
        newTaxonNameForRegistration = getRepo().getNameService().find(nameSaveEvent.getEntityId());
228
        TaxonNamePopupEditor popup = getNavigationManager().showInPopup(TaxonNamePopupEditor.class);
229
        popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE,CRUD.DELETE));
230
        popup.withDeleteButton(true);
231
        popup.loadInEditor(newTaxonNameForRegistration.getId());
232
        // disable NomReferenceCombobox:
233
        // the in the registration application inReferences should only edited centrally
234
        popup.getNomReferenceCombobox().setEnabled(false);
235
    }
236

    
237
    /**
238
     * Creates a new <code>Registration</code> for a new name that has just been edited
239
     * using the <code>TaxonNamePopupEditor</code>. The new name was previously created
240
     * in this presenter as <code>newTaxonNameForRegistration</code> (see {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)})
241
     * and is either filled with data (<code>Reason.SAVE</code>) or it is still empty
242
     * (<code>Reason.CANCEL</code>).
243
     *
244
     *
245
     * @param event
246
     * @throws RegistrationValidationException
247
     */
248
    @EventListener
249
    public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
250
        if(event.getPopup() instanceof TaxonNamePopupEditor){
251
            if(event.getReason().equals(Reason.SAVE)){
252
                if(newTaxonNameForRegistration != null){
253
                    int taxonNameId = newTaxonNameForRegistration.getId();
254
                    getRepo().getSession().refresh(newTaxonNameForRegistration);
255
                    Registration reg = createNewRegistrationForName(taxonNameId);
256
                    workingset.add(reg);
257
                }
258
                refreshView();
259
            } else if(event.getReason().equals(Reason.CANCEL)){
260
                // clean up
261
                getTaxonNameStore().deleteBean(newTaxonNameForRegistration);
262
            }
263
            newTaxonNameForRegistration = null;
264
        }
265
    }
266

    
267

    
268
    /**
269
     * Creates a new Registration for an exiting (previously published name).
270
     *
271
     * @param event
272
     * @throws RegistrationValidationException
273
     */
274
    @EventListener(condition = "#event.action == T(eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkingsetAction.Action).start")
275
    public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event) throws RegistrationValidationException {
276

    
277
        getView().getAddExistingNameCombobox().commit();
278
        TaxonName typifiedName = getView().getAddExistingNameCombobox().getValue();
279
        if(typifiedName != null){
280
            Registration newRegistrationWithExistingName = createNewRegistrationForName(null);
281
            Reference citation = getRepo().getReferenceService().find(workingset.getCitationId());
282
            newRegistrationDTOWithExistingName = new RegistrationDTO(newRegistrationWithExistingName, typifiedName, citation);
283
            workingset.add(newRegistrationDTOWithExistingName);
284
            // tell the view to update the workingset
285
            getView().setWorkingset(workingset);
286
            getView().getAddExistingNameRegistrationButton().setEnabled(false);
287
            getView().getAddExistingNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
288
        } else {
289
            logger.error("Seletced name is NULL");
290
        }
291

    
292
    }
293

    
294
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
295
    public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event) {
296

    
297
            if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET ){
298
                SpecimenTypeDesignationWorkingsetPopupEditor popup = getNavigationManager().showInPopup(SpecimenTypeDesignationWorkingsetPopupEditor.class);
299
                popup.withDeleteButton(true);
300
                popup.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event.getRegistrationId(), event.getEntityId()));
301
            } else {
302
                // TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET
303
                // FIXME implement NameTypeDesignationWorkingsetPopupEditor
304
            }
305
    }
306

    
307
    @EventListener(condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).ADD && #event.sourceComponent == null")
308
    public void onAddNewTypeDesignationWorkingset(TypeDesignationWorkingsetEditorAction event) {
309

    
310
        if(event.getWorkingSetType() == TypeDesignationWorkingSetType.SPECIMEN_TYPE_DESIGNATION_WORKINGSET){
311
            SpecimenTypeDesignationWorkingsetPopupEditor popup = getNavigationManager().showInPopup(SpecimenTypeDesignationWorkingsetPopupEditor.class);
312
            TypeDesignationWorkingsetEditorIdSet identifierSet;
313
            Integer typifiedNameId;
314
            if(newRegistrationDTOWithExistingName != null){
315
                typifiedNameId = newRegistrationDTOWithExistingName.getTypifiedName().getId();
316
            } else {
317
                RegistrationDTO registrationDTO = workingset.getRegistrationDTO(event.getRegistrationId()).get();
318
                EntityReference typifiedNameRef = registrationDTO.getTypifiedName();
319
                if(typifiedNameRef != null){
320
                    // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
321
                    typifiedNameId = typifiedNameRef.getId();
322
                } else {
323
                    // case of registrations with a name in the nomenclatural act.
324
                    typifiedNameId = registrationDTO.getName().getId();
325
                }
326
            }
327
            identifierSet = new TypeDesignationWorkingsetEditorIdSet(
328
                    event.getRegistrationId(),
329
                    getView().getCitationID(),
330
                    typifiedNameId
331
                    );
332
            popup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE));
333
            popup.loadInEditor(identifierSet);
334
            popup.withDeleteButton(true);
335
        } else {
336
            // TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET
337
            // FIXME implement NameTypeDesignationWorkingsetPopupEditor
338
        }
339
    }
340

    
341
    /**
342
     * Performs final actions after a TypeDesignationEditor which has been
343
     * opened to add a TypeDesignation to a Registration object which was
344
     * created for an previously published name. Prior adding a typedesignation,
345
     * the according Registration object is dangling, that has no association to
346
     * any entity denoting an nomenclatural act which has a reference to a
347
     * publication. This means that the registration object is not in the
348
     * working set.
349
     *
350
     *
351
     * @param event
352
     * @throws RegistrationValidationException
353
     */
354
    @EventListener
355
    public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event) throws RegistrationValidationException{
356
        if(event.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor){
357
            if(event.getReason().equals(Reason.SAVE)){
358
                refreshView();
359
            } else if(event.getReason().equals(Reason.CANCEL)){
360
                // clean up
361
                if(newRegistrationDTOWithExistingName != null){
362
                    getRegistrationStore().deleteBean(newRegistrationDTOWithExistingName.registration());
363
                }
364
            }
365
            // set newRegistrationDTOWithExistingName NULL in any case
366
            newRegistrationDTOWithExistingName = null;
367
        }
368
    }
369

    
370

    
371
    @EventListener(classes=ShowDetailsEvent.class, condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet)")
372
    public void onShowRegistrationWorkingSetMessages(ShowDetailsEvent<?,?> event) { // WARNING don't use more specific generic type arguments
373
        List<String> messages = new ArrayList<>();
374
        for(RegistrationDTO dto : workingset.getRegistrationDTOs()){
375
            dto.getMessages().forEach(m -> messages.add(dto.getSummary() + ": " + m));
376
        }
377
        if(event.getProperty().equals("messages")){
378
            getView().openDetailsPopup("Messages", messages);
379
        }
380
    }
381

    
382
    @EventListener(classes=ShowDetailsEvent.class, condition = "#event.type == T(eu.etaxonomy.cdm.vaadin.view.registration.RegistrationDTO)")
383
    public void onShowRegistrationMessages(ShowDetailsEvent<?,?> event) { // WARNING don't use more specific generic type arguments
384
        RegistrationDTO regDto = workingSetService.loadDtoById((Integer)event.getIdentifier());
385
        if(event.getProperty().equals("messages")){
386
            if(getView() != null){
387
                getView().openDetailsPopup("Messages", regDto.getMessages());
388
            }
389
        }
390
    }
391

    
392
    @EventListener
393
    public void onEntityChangeEvent(EntityChangeEvent event){
394
        if(workingset == null){
395
            return;
396
        }
397
        if(Reference.class.isAssignableFrom(event.getEntityType())){
398
            if(workingset.getCitationId().equals(event.getEntityId())){
399
                refreshView();
400
            }
401
        } else
402
        if(Registration.class.isAssignableFrom(event.getEntityType())){
403
            if(workingset.getRegistrations().stream().anyMatch(reg -> reg.getId() == event.getEntityId())){
404
                refreshView();
405
            }
406
        } else
407
        if(TaxonName.class.isAssignableFrom(event.getEntityType())){
408
            if(workingset.getRegistrationDTOs().stream().anyMatch(reg ->
409
                reg.getTypifiedName() != null
410
                && reg.getTypifiedName().getId() == event.getEntityId())){
411
                    refreshView();
412
            }
413
        } else
414
        if(TypeDesignationBase.class.isAssignableFrom(event.getEntityType())){
415
            if(workingset.getRegistrationDTOs().stream().anyMatch(
416
                    reg -> reg.getTypeDesignations().stream().anyMatch(
417
                            td -> td.getId() == event.getEntityId()
418
                            )
419
                        )
420
                    ){
421
                refreshView();
422
            }
423
        }
424

    
425
    }
426

    
427
}
(12-12/19)