Project

General

Profile

Download (17.9 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2018 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.name;
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.UUID;
17

    
18
import org.apache.log4j.Logger;
19
import org.hibernate.criterion.Restrictions;
20
import org.springframework.beans.factory.annotation.Autowired;
21
import org.springframework.context.annotation.Scope;
22
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
23

    
24
import com.vaadin.spring.annotation.SpringComponent;
25

    
26
import eu.etaxonomy.cdm.api.service.DeleteResult;
27
import eu.etaxonomy.cdm.api.service.IService;
28
import eu.etaxonomy.cdm.api.service.dto.RegistrationDTO;
29
import eu.etaxonomy.cdm.api.service.name.TypeDesignationWorkingSet;
30
import eu.etaxonomy.cdm.api.service.registration.IRegistrationWorkingSetService;
31
import eu.etaxonomy.cdm.format.reference.ReferenceEllypsisFormatter;
32
import eu.etaxonomy.cdm.format.reference.ReferenceEllypsisFormatter.LabelType;
33
import eu.etaxonomy.cdm.model.common.Annotation;
34
import eu.etaxonomy.cdm.model.common.AnnotationType;
35
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
36
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
37
import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
38
import eu.etaxonomy.cdm.model.name.TaxonName;
39
import eu.etaxonomy.cdm.model.permission.CRUD;
40
import eu.etaxonomy.cdm.model.reference.Reference;
41
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
42
import eu.etaxonomy.cdm.model.reference.ReferenceType;
43
import eu.etaxonomy.cdm.persistence.dao.initializer.EntityInitStrategy;
44
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
45
import eu.etaxonomy.cdm.service.CdmStore;
46
import eu.etaxonomy.cdm.service.UserHelperAccess;
47
import eu.etaxonomy.cdm.vaadin.event.EditorActionTypeFilter;
48
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
49
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent.Type;
50
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
51
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
52
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityButtonUpdater;
53
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityReloader;
54
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
55
import eu.etaxonomy.cdm.vaadin.ui.config.TaxonNamePopupEditorConfig;
56
import eu.etaxonomy.cdm.vaadin.util.ReferenceEllypsisCaptionGenerator;
57
import eu.etaxonomy.cdm.vaadin.view.reference.ReferencePopupEditor;
58
import eu.etaxonomy.cdm.vaadin.view.reference.RegistrationUiReferenceEditorFormConfigurator;
59
import eu.etaxonomy.vaadin.mvp.AbstractCdmEditorPresenter;
60
import eu.etaxonomy.vaadin.mvp.AbstractView;
61
import eu.etaxonomy.vaadin.mvp.BeanInstantiator;
62
import eu.etaxonomy.vaadin.mvp.BoundField;
63
import eu.etaxonomy.vaadin.ui.view.PopupView;
64

    
65
/**
66
 * @author a.kohlbecker
67
 * @since Jan 26, 2018
68
 *
69
 */
70
@SpringComponent
71
@Scope("prototype")
72
public class NameTypeDesignationPresenter
73
        extends AbstractCdmEditorPresenter<NameTypeDesignation, NameTypeDesignationEditorView> {
74

    
75
    private static final long serialVersionUID = 896305051895903033L;
76

    
77
    public static final Logger logger = Logger.getLogger(SpecimenTypeDesignationWorkingsetEditorPresenter.class);
78

    
79
    @Autowired
80
    private IRegistrationWorkingSetService registrationWorkingSetService;
81

    
82
    HashSet<TaxonName> typifiedNamesAsLoaded;
83

    
84
    private TaxonName typifiedNameInContext;
85

    
86
    /**
87
     * The unit of publication in which the type designation has been published.
88
     * This may be any type listed in {@link RegistrationUIDefaults#NOMECLATURAL_PUBLICATION_UNIT_TYPES}
89
     * but never a {@link ReferenceType#Section}
90
     */
91
    private DescriptionElementSource publishedUnit;
92

    
93
    protected static BeanInstantiator<NameTypeDesignation> defaultBeanInstantiator = new BeanInstantiator<NameTypeDesignation>() {
94

    
95
        @Override
96
        public NameTypeDesignation createNewBean() {
97
            return NameTypeDesignation.NewInstance();
98
        }
99
    };
100

    
101
    private CdmFilterablePagingProvider<Reference,Reference> referencePagingProvider;
102

    
103
    private BeanInstantiator<Reference> newReferenceInstantiator;
104

    
105

    
106
    @Override
107
    protected BeanInstantiator<NameTypeDesignation> defaultBeanInstantiator(){
108
       return defaultBeanInstantiator;
109
    }
110

    
111
    /**
112
     * {@inheritDoc}
113
     */
114
    @Override
115
    protected NameTypeDesignation loadBeanById(Object identifier) {
116
        NameTypeDesignation bean;
117
        if(identifier instanceof Integer || identifier == null){
118
            bean = super.loadBeanById(identifier);
119
        } else {
120
            TypeDesignationWorkingsetIds idset = (TypeDesignationWorkingsetIds)identifier;
121
            RegistrationDTO regDTO = registrationWorkingSetService.loadDtoByUuid(idset.registrationUuid);
122
            typifiedNameInContext = regDTO.typifiedName();
123
            // find the working set
124
            TypeDesignationWorkingSet typeDesignationWorkingSet = regDTO.getTypeDesignationWorkingSet(idset.baseEntityRef);
125
            if(!typeDesignationWorkingSet.getBaseEntityReference().getType().equals(NameTypeDesignation.class)){
126
                throw new RuntimeException("TypeDesignationWorkingsetEditorIdSet references not a NameTypeDesignation");
127
            } else {
128
                // TypeDesignationWorkingSet for NameTyped only contain one item!!!
129
                UUID nameTypeDesignationUuid = typeDesignationWorkingSet.getTypeDesignations().get(0).getUuid();
130
                bean = super.loadBeanById(nameTypeDesignationUuid);
131
            }
132
        }
133

    
134
        try {
135
            setPublishedUnit(bean.getTypifiedNames().iterator().next().getNomenclaturalSource());
136
        } catch (Exception e) {
137
            // FIXME report error state instead
138
            logger.error("Error on finding published unit in " + bean, e);
139
        }
140

    
141
        if (getPublishedUnit() != null) {
142
            // reduce available references to those which are sections of
143
            // the publicationUnit and the publishedUnit itself
144
            referencePagingProvider.getCriteria()
145
                    .add(Restrictions.or(
146
                            Restrictions.and(
147
                                    Restrictions.eq("inReference", publishedUnit.getCitation()),
148
                                    Restrictions.eq("type", ReferenceType.Section)),
149
                            Restrictions.idEq(publishedUnit.getCitation().getId()))
150
                         );
151

    
152
            // new Reference only a sub sections of the publishedUnit
153
            newReferenceInstantiator = new BeanInstantiator<Reference>() {
154
                @Override
155
                public Reference createNewBean() {
156
                    Reference newRef = ReferenceFactory.newSection();
157
                    newRef.setInReference(publishedUnit.getCitation());
158
                    return newRef;
159
                }
160
            };
161
        }
162

    
163
        return bean;
164
    }
165

    
166

    
167
    /**
168
     * {@inheritDoc}
169
     */
170
    @Override
171
    protected NameTypeDesignation loadCdmEntity(UUID uuid) {
172
        EntityInitStrategy initStrategy = new EntityInitStrategy(Arrays.asList(new String []{
173
                "$",
174
                "annotations.*", // * is needed as log as we are using a table in FilterableAnnotationsField
175
                "typifiedNames.typeDesignations", // important !!
176
                "typifiedNames.nomenclaturalSource.citation",
177
                "typeName.$",
178
                "source.citation",
179
                "source.annotations",
180
                "source.markers",
181
                "source.links",
182
                }
183
        ));
184

    
185
        initStrategy.extend("citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
186
        NameTypeDesignation typeDesignation;
187
        if(uuid != null){
188
            typeDesignation = (NameTypeDesignation) getRepo().getNameService().loadTypeDesignation(uuid, initStrategy.getPropertyPaths());
189
        } else {
190
            typeDesignation = createNewBean();
191
        }
192

    
193
        typifiedNamesAsLoaded = new HashSet<>(typeDesignation.getTypifiedNames());
194

    
195
        return typeDesignation;
196
    }
197

    
198

    
199
    /**
200
     * {@inheritDoc}
201
     */
202
    @Override
203
    public void handleViewEntered() {
204

    
205
        getView().getTypeStatusSelect().setContainerDataSource(cdmBeanItemContainerFactory.buildBeanItemContainer(NameTypeDesignationStatus.class));
206
        getView().getTypeStatusSelect().setItemCaptionPropertyId("description");
207

    
208
        getView().getDesignationReferenceCombobox().getSelect().setCaptionGenerator(
209
                new ReferenceEllypsisCaptionGenerator(LabelType.BIBLIOGRAPHIC, getView().getDesignationReferenceCombobox().getSelect())
210
                );
211
        referencePagingProvider = pagingProviderFactory.referencePagingProvider();
212
        getView().getDesignationReferenceCombobox().loadFrom(referencePagingProvider, referencePagingProvider, referencePagingProvider.getPageSize());
213
        getView().getDesignationReferenceCombobox().setNestedButtonStateUpdater(new ToOneRelatedEntityButtonUpdater<Reference>(getView().getDesignationReferenceCombobox()));
214
        getView().getDesignationReferenceCombobox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getDesignationReferenceCombobox(), this));
215

    
216
        CdmFilterablePagingProvider<TaxonName,TaxonName> namePagingProvider = pagingProviderFactory.taxonNamesWithoutOrthophicIncorrect();
217
        getView().getTypeNameField().loadFrom(namePagingProvider, namePagingProvider, namePagingProvider.getPageSize());
218
        getView().getTypeNameField().setNestedButtonStateUpdater(new ToOneRelatedEntityButtonUpdater<TaxonName>(getView().getTypeNameField()));
219
        getView().getTypeNameField().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getTypeNameField(), this));
220

    
221
        getView().getTypifiedNamesComboboxSelect().setPagingProviders(namePagingProvider, namePagingProvider, namePagingProvider.getPageSize(), this);
222

    
223
        getView().getAnnotationsField().setAnnotationTypeItemContainer(cdmBeanItemContainerFactory.buildVocabularyTermsItemContainer(
224
                AnnotationType.EDITORIAL().getVocabulary().getUuid()));
225

    
226
    }
227

    
228
    @Override
229
    protected void guaranteePerEntityCRUDPermissions(UUID identifier) {
230
        if(crud != null){
231
            newAuthorityCreated = UserHelperAccess.userHelper().createAuthorityForCurrentUser(NameTypeDesignation.class, identifier, crud, null);
232
        }
233
    }
234

    
235
    @Override
236
    protected void guaranteePerEntityCRUDPermissions(NameTypeDesignation bean) {
237
        // TODO Auto-generated method stub
238

    
239
    }
240

    
241

    
242
    @Override
243
    protected IService<NameTypeDesignation> getService() {
244
        // No TypeDesignationService :( so I need override the generic save and delete methods
245
        return null;
246
    }
247

    
248
    @Override
249
    protected void deleteBean(NameTypeDesignation bean){
250
        // deleteTypedesignation(uuid, uuid) needs to be called so the name is loaded in the transaction of the method and is saved.
251
        DeleteResult deletResult = getRepo().getNameService().deleteTypeDesignation(typifiedNameInContext.getUuid(), bean.getUuid());
252
        if(deletResult.isOk()){
253
            EntityChangeEvent changeEvent = new EntityChangeEvent(bean, Type.REMOVED, (AbstractView) getView());
254
            viewEventBus.publish(this, changeEvent);
255
        } else {
256
            CdmStore.handleDeleteresultInError(deletResult);
257
        }
258
    }
259

    
260

    
261
    /**
262
     * {@inheritDoc}
263
     */
264
    @Override
265
    protected NameTypeDesignation preSaveBean(NameTypeDesignation bean) {
266

    
267
        if(!bean.hasDesignationSource()) {
268
            bean.setSource(null); // this effectively removes the designation reference and reference detail
269
        }
270

    
271
        // the typifiedNames can only be set on the name side, so we need to
272
        // handle changes explicitly here
273
        HashSet<TaxonName> typifiedNames = new HashSet<>(bean.getTypifiedNames());
274

    
275
        // handle adds
276
        for(TaxonName name : typifiedNames){
277
            if(name == null){
278
                throw new NullPointerException("typifiedName must not be null");
279
            }
280
            if(!name.getTypeDesignations().contains(bean)){
281
                name.addTypeDesignation(bean, false);
282
            }
283
        }
284
        // handle removed
285
        for(TaxonName name : typifiedNamesAsLoaded){
286
            if(!typifiedNames.contains(name)){
287
                name.removeTypeDesignation(bean);
288
            }
289
            // FIXME do we need to save the names here or is the delete cascaded from the typedesignation to the name?
290
        }
291

    
292
        // handle annotation changes
293
        List<Annotation> annotations = getView().getAnnotationsField().getValue();
294
        List<Annotation> currentAnnotations = new ArrayList<>(bean.getAnnotations());
295
        List<Annotation> annotationsSeen = new ArrayList<>();
296
        for(Annotation a : annotations){
297
            if(a == null){
298
                continue;
299
            }
300
            if(!currentAnnotations.contains(a)){
301
                bean.addAnnotation(a);
302
            }
303
            annotationsSeen.add(a);
304
        }
305
        for(Annotation a : currentAnnotations){
306
            if(!annotationsSeen.contains(a)){
307
                bean.removeAnnotation(a);
308
            }
309
        }
310

    
311

    
312
        return bean;
313
    }
314

    
315

    
316

    
317
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
318
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction action){
319

    
320
        if(!isFromOwnView(action)){
321
            return;
322
        }
323

    
324
        TaxonNamePopupEditor typeNamePopup = openPopupEditor(TaxonNamePopupEditor.class, action);
325
        typeNamePopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
326
        typeNamePopup.withDeleteButton(true);
327
        TaxonNamePopupEditorConfig.configure(typeNamePopup);
328
        typeNamePopup.loadInEditor(null);
329

    
330
    }
331

    
332

    
333
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
334
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction action){
335

    
336
        if(!isFromOwnView(action)){
337
            return;
338
        }
339

    
340
        TaxonNamePopupEditor typeNamePopup = openPopupEditor(TaxonNamePopupEditor.class, action);
341
        typeNamePopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
342
        typeNamePopup.withDeleteButton(true);
343
        TaxonNamePopupEditorConfig.configure(typeNamePopup);
344
        typeNamePopup.loadInEditor(action.getEntityUuid());
345

    
346
    }
347

    
348
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
349
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
350

    
351
        if (getView() == null || event.getSourceView() != getView()) {
352
            return;
353
        }
354

    
355
        ReferencePopupEditor referenceEditorPopup = openPopupEditor(ReferencePopupEditor.class, event);
356

    
357
        referenceEditorPopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
358
        referenceEditorPopup.withDeleteButton(true);
359
        configureReferencePopupEditor(referenceEditorPopup, null);
360
    }
361

    
362
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
363
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
364

    
365
        if (!isFromOwnView(event)) {
366
            return;
367
        }
368
        ReferencePopupEditor referenceEditorPopup = openPopupEditor(ReferencePopupEditor.class, event);
369

    
370
        referenceEditorPopup.withDeleteButton(true);
371
        configureReferencePopupEditor(referenceEditorPopup, event.getEntityUuid());
372
    }
373

    
374
    @EventBusListenerMethod
375
    public void onEntityChangeEvent(EntityChangeEvent<?>event){
376

    
377
        BoundField boundTargetField = boundTargetField((PopupView) event.getSourceView());
378

    
379
        if(boundTargetField != null){
380
            if(boundTargetField.matchesPropertyIdPath("typeName")){
381
                if(event.isCreateOrModifiedType()){
382
                    getCache().load(event.getEntity());
383
                    if(event.isCreatedType()){
384
                        getView().getTypeNameField().setValue((TaxonName) event.getEntity());
385
                    } else {
386
                        getView().getTypeNameField().reload();
387
                    }
388
                }
389
                if(event.isRemovedType()){
390
                    getView().getTypeNameField().selectNewItem(null);
391
                }
392

    
393
            }
394
        }
395
    }
396

    
397
    /**
398
     * @return
399
     *  the {@link #publishedUnit}
400
     */
401
    public DescriptionElementSource getPublishedUnit() {
402
        return publishedUnit;
403
    }
404

    
405
    /**
406
     * @param publishedUnit
407
     *  The unit of publication in which the type designation has been published.
408
     *  This may be any type listed in {@link RegistrationUIDefaults#NOMECLATURAL_PUBLICATION_UNIT_TYPES}
409
     */
410
    protected void setPublishedUnit(DescriptionElementSource publishedUnit) throws Exception {
411
        if(publishedUnit == null) {
412
            throw new NullPointerException();
413
        }
414
        if(publishedUnit.getCitation() == null) {
415
            throw new NullPointerException("The citation of the published unit must not be null.");
416
        }
417
        if(!RegistrationUIDefaults.NOMECLATURAL_PUBLICATION_UNIT_TYPES.contains(publishedUnit.getCitation().getType())) {
418
            throw new Exception("The referrence type '"  + publishedUnit.getType() + "'is not allowed for publishedUnit.");
419
        }
420
        this.publishedUnit = publishedUnit;
421
    }
422

    
423
    /**
424
     * @param referenceEditorPopup
425
     */
426
    private void configureReferencePopupEditor(ReferencePopupEditor referenceEditorPopup, UUID referenceUUID) {
427

    
428
        if (newReferenceInstantiator != null) {
429
            referenceEditorPopup.setBeanInstantiator(newReferenceInstantiator);
430
        }
431

    
432
        // TODO this should be configurable per UI -
433
        // RegistrationUiReferenceEditorFormConfigurator as spring bean,
434
        // different spring profiles
435
        // see also similar methods in TaxonName and SpecimenTypeDesigationEditors
436
        referenceEditorPopup.setEditorComponentsConfigurator(new RegistrationUiReferenceEditorFormConfigurator(newReferenceInstantiator != null));
437

    
438
        referenceEditorPopup.loadInEditor(referenceUUID);
439
        // TODO limit ??? referenceEditorPopup.getTypeSelect().setValue(ReferenceType.Article);
440

    
441
    }
442

    
443
}
(4-4/17)