Project

General

Profile

Download (15.3 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.ReferenceType;
42
import eu.etaxonomy.cdm.persistence.dao.initializer.EntityInitStrategy;
43
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
44
import eu.etaxonomy.cdm.service.CdmStore;
45
import eu.etaxonomy.cdm.service.UserHelperAccess;
46
import eu.etaxonomy.cdm.vaadin.event.EditorActionTypeFilter;
47
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
48
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent.Type;
49
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
50
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityButtonUpdater;
51
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityReloader;
52
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
53
import eu.etaxonomy.cdm.vaadin.ui.config.TaxonNamePopupEditorConfig;
54
import eu.etaxonomy.cdm.vaadin.util.ReferenceEllypsisCaptionGenerator;
55
import eu.etaxonomy.vaadin.mvp.AbstractCdmEditorPresenter;
56
import eu.etaxonomy.vaadin.mvp.AbstractView;
57
import eu.etaxonomy.vaadin.mvp.BeanInstantiator;
58
import eu.etaxonomy.vaadin.mvp.BoundField;
59
import eu.etaxonomy.vaadin.ui.view.PopupView;
60

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

    
71
    private static final long serialVersionUID = 896305051895903033L;
72

    
73
    public static final Logger logger = Logger.getLogger(SpecimenTypeDesignationWorkingsetEditorPresenter.class);
74

    
75
    @Autowired
76
    private IRegistrationWorkingSetService registrationWorkingSetService;
77

    
78
    HashSet<TaxonName> typifiedNamesAsLoaded;
79

    
80
    private TaxonName typifiedNameInContext;
81

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

    
89
    protected static BeanInstantiator<NameTypeDesignation> defaultBeanInstantiator = new BeanInstantiator<NameTypeDesignation>() {
90

    
91
        @Override
92
        public NameTypeDesignation createNewBean() {
93
            return NameTypeDesignation.NewInstance();
94
        }
95
    };
96

    
97
    private CdmFilterablePagingProvider<Reference,Reference> referencePagingProvider;
98

    
99

    
100
    @Override
101
    protected BeanInstantiator<NameTypeDesignation> defaultBeanInstantiator(){
102
       return defaultBeanInstantiator;
103
    }
104

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

    
128
        try {
129
            setPublishedUnit(bean.getTypifiedNames().iterator().next().getNomenclaturalSource());
130
        } catch (Exception e) {
131
            // FIXME report error state instead
132
            logger.error("Error on finding published unit in " + bean, e);
133
        }
134

    
135
        if (getPublishedUnit() != null) {
136
            // reduce available references to those which are sections of
137
            // the publicationUnit and the publishedUnit itself
138
            referencePagingProvider.getCriteria()
139
                    .add(Restrictions.or(
140
                            Restrictions.and(
141
                                    Restrictions.eq("inReference", publishedUnit.getCitation()),
142
                                    Restrictions.eq("type", ReferenceType.Section)),
143
                            Restrictions.idEq(publishedUnit.getCitation().getId()))
144
                         );
145
        }
146

    
147
        return bean;
148
    }
149

    
150

    
151
    /**
152
     * {@inheritDoc}
153
     */
154
    @Override
155
    protected NameTypeDesignation loadCdmEntity(UUID uuid) {
156
        EntityInitStrategy initStrategy = new EntityInitStrategy(Arrays.asList(new String []{
157
                "$",
158
                "annotations.*", // * is needed as log as we are using a table in FilterableAnnotationsField
159
                "typifiedNames.typeDesignations", // important !!
160
                "typifiedNames.nomenclaturalSource.citation",
161
                "typeName.$",
162
                "source.citation",
163
                "source.annotations",
164
                "source.markers",
165
                "source.links",
166
                }
167
        ));
168

    
169
        initStrategy.extend("citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
170
        NameTypeDesignation typeDesignation;
171
        if(uuid != null){
172
            typeDesignation = (NameTypeDesignation) getRepo().getNameService().loadTypeDesignation(uuid, initStrategy.getPropertyPaths());
173
        } else {
174
            typeDesignation = createNewBean();
175
        }
176

    
177
        typifiedNamesAsLoaded = new HashSet<>(typeDesignation.getTypifiedNames());
178

    
179
        return typeDesignation;
180
    }
181

    
182

    
183
    /**
184
     * {@inheritDoc}
185
     */
186
    @Override
187
    public void handleViewEntered() {
188

    
189
        getView().getTypeStatusSelect().setContainerDataSource(cdmBeanItemContainerFactory.buildBeanItemContainer(NameTypeDesignationStatus.class));
190
        getView().getTypeStatusSelect().setItemCaptionPropertyId("description");
191

    
192
        getView().getDesignationReferenceCombobox().getSelect().setCaptionGenerator(
193
                new ReferenceEllypsisCaptionGenerator(LabelType.BIBLIOGRAPHIC, getView().getDesignationReferenceCombobox().getSelect())
194
                );
195
        referencePagingProvider = pagingProviderFactory.referencePagingProvider();
196
        getView().getDesignationReferenceCombobox().loadFrom(referencePagingProvider, referencePagingProvider, referencePagingProvider.getPageSize());
197
        getView().getDesignationReferenceCombobox().setNestedButtonStateUpdater(new ToOneRelatedEntityButtonUpdater<Reference>(getView().getDesignationReferenceCombobox()));
198
        getView().getDesignationReferenceCombobox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getDesignationReferenceCombobox(), this));
199

    
200
        CdmFilterablePagingProvider<TaxonName,TaxonName> namePagingProvider = pagingProviderFactory.taxonNamesWithoutOrthophicIncorrect();
201
        getView().getTypeNameField().loadFrom(namePagingProvider, namePagingProvider, namePagingProvider.getPageSize());
202
        getView().getTypeNameField().setNestedButtonStateUpdater(new ToOneRelatedEntityButtonUpdater<TaxonName>(getView().getTypeNameField()));
203
        getView().getTypeNameField().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getTypeNameField(), this));
204

    
205
        getView().getTypifiedNamesComboboxSelect().setPagingProviders(namePagingProvider, namePagingProvider, namePagingProvider.getPageSize(), this);
206

    
207
        getView().getAnnotationsField().setAnnotationTypeItemContainer(cdmBeanItemContainerFactory.buildVocabularyTermsItemContainer(
208
                AnnotationType.EDITORIAL().getVocabulary().getUuid()));
209

    
210
    }
211

    
212
    @Override
213
    protected void guaranteePerEntityCRUDPermissions(UUID identifier) {
214
        if(crud != null){
215
            newAuthorityCreated = UserHelperAccess.userHelper().createAuthorityForCurrentUser(NameTypeDesignation.class, identifier, crud, null);
216
        }
217
    }
218

    
219
    @Override
220
    protected void guaranteePerEntityCRUDPermissions(NameTypeDesignation bean) {
221
        // TODO Auto-generated method stub
222

    
223
    }
224

    
225

    
226
    @Override
227
    protected IService<NameTypeDesignation> getService() {
228
        // No TypeDesignationService :( so I need override the generic save and delete methods
229
        return null;
230
    }
231

    
232
    @Override
233
    protected void deleteBean(NameTypeDesignation bean){
234
        // deleteTypedesignation(uuid, uuid) needs to be called so the name is loaded in the transaction of the method and is saved.
235
        DeleteResult deletResult = getRepo().getNameService().deleteTypeDesignation(typifiedNameInContext.getUuid(), bean.getUuid());
236
        if(deletResult.isOk()){
237
            EntityChangeEvent changeEvent = new EntityChangeEvent(bean, Type.REMOVED, (AbstractView) getView());
238
            viewEventBus.publish(this, changeEvent);
239
        } else {
240
            CdmStore.handleDeleteresultInError(deletResult);
241
        }
242
    }
243

    
244

    
245
    /**
246
     * {@inheritDoc}
247
     */
248
    @Override
249
    protected NameTypeDesignation preSaveBean(NameTypeDesignation bean) {
250

    
251
        if(!bean.hasDesignationSource()) {
252
            bean.setSource(null); // this effectively removes the designation reference and reference detail
253
        }
254

    
255
        // the typifiedNames can only be set on the name side, so we need to
256
        // handle changes explicitly here
257
        HashSet<TaxonName> typifiedNames = new HashSet<>(bean.getTypifiedNames());
258

    
259
        // handle adds
260
        for(TaxonName name : typifiedNames){
261
            if(name == null){
262
                throw new NullPointerException("typifiedName must not be null");
263
            }
264
            if(!name.getTypeDesignations().contains(bean)){
265
                name.addTypeDesignation(bean, false);
266
            }
267
        }
268
        // handle removed
269
        for(TaxonName name : typifiedNamesAsLoaded){
270
            if(!typifiedNames.contains(name)){
271
                name.removeTypeDesignation(bean);
272
            }
273
            // FIXME do we need to save the names here or is the delete cascaded from the typedesignation to the name?
274
        }
275

    
276
        // handle annotation changes
277
        List<Annotation> annotations = getView().getAnnotationsField().getValue();
278
        List<Annotation> currentAnnotations = new ArrayList<>(bean.getAnnotations());
279
        List<Annotation> annotationsSeen = new ArrayList<>();
280
        for(Annotation a : annotations){
281
            if(a == null){
282
                continue;
283
            }
284
            if(!currentAnnotations.contains(a)){
285
                bean.addAnnotation(a);
286
            }
287
            annotationsSeen.add(a);
288
        }
289
        for(Annotation a : currentAnnotations){
290
            if(!annotationsSeen.contains(a)){
291
                bean.removeAnnotation(a);
292
            }
293
        }
294

    
295

    
296
        return bean;
297
    }
298

    
299

    
300

    
301
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
302
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction action){
303

    
304
        if(!isFromOwnView(action)){
305
            return;
306
        }
307

    
308
        TaxonNamePopupEditor typeNamePopup = openPopupEditor(TaxonNamePopupEditor.class, action);
309
        typeNamePopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
310
        typeNamePopup.withDeleteButton(true);
311
        TaxonNamePopupEditorConfig.configure(typeNamePopup);
312
        typeNamePopup.loadInEditor(null);
313

    
314
    }
315

    
316

    
317
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
318
    public void onTaxonNameEditorActionEdit(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(action.getEntityUuid());
329

    
330
    }
331

    
332
    @EventBusListenerMethod
333
    public void onEntityChangeEvent(EntityChangeEvent<?>event){
334

    
335
        BoundField boundTargetField = boundTargetField((PopupView) event.getSourceView());
336

    
337
        if(boundTargetField != null){
338
            if(boundTargetField.matchesPropertyIdPath("typeName")){
339
                if(event.isCreateOrModifiedType()){
340
                    getCache().load(event.getEntity());
341
                    if(event.isCreatedType()){
342
                        getView().getTypeNameField().setValue((TaxonName) event.getEntity());
343
                    } else {
344
                        getView().getTypeNameField().reload();
345
                    }
346
                }
347
                if(event.isRemovedType()){
348
                    getView().getTypeNameField().selectNewItem(null);
349
                }
350

    
351
            }
352
        }
353
    }
354

    
355
    /**
356
     * @return
357
     *  the {@link #publishedUnit}
358
     */
359
    public DescriptionElementSource getPublishedUnit() {
360
        return publishedUnit;
361
    }
362

    
363
    /**
364
     * @param publishedUnit
365
     *  The unit of publication in which the type designation has been published.
366
     *  This may be any type listed in {@link RegistrationUIDefaults#NOMECLATURAL_PUBLICATION_UNIT_TYPES}
367
     */
368
    protected void setPublishedUnit(DescriptionElementSource publishedUnit) throws Exception {
369
        if(publishedUnit == null) {
370
            throw new NullPointerException();
371
        }
372
        if(publishedUnit.getCitation() == null) {
373
            throw new NullPointerException("The citation of the published unit must not be null.");
374
        }
375
        if(!RegistrationUIDefaults.NOMECLATURAL_PUBLICATION_UNIT_TYPES.contains(publishedUnit.getCitation().getType())) {
376
            throw new Exception("The referrence type '"  + publishedUnit.getType() + "'is not allowed for publishedUnit.");
377
        }
378
        this.publishedUnit = publishedUnit;
379
    }
380

    
381
}
(4-4/17)