Project

General

Profile

Download (42.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.name;
10

    
11
import java.util.Arrays;
12
import java.util.EnumSet;
13
import java.util.HashMap;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.UUID;
17

    
18
import org.apache.commons.lang.StringUtils;
19
import org.apache.log4j.Logger;
20
import org.hibernate.criterion.Restrictions;
21
import org.springframework.context.annotation.Scope;
22
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
23
import org.vaadin.viritin.fields.AbstractElementCollection;
24

    
25
import com.vaadin.data.Property;
26
import com.vaadin.data.util.BeanItemContainer;
27
import com.vaadin.spring.annotation.SpringComponent;
28
import com.vaadin.ui.AbstractField;
29
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
30
import com.vaadin.ui.Field;
31

    
32
import eu.etaxonomy.cdm.api.service.INameService;
33
import eu.etaxonomy.cdm.format.reference.ReferenceEllypsisFormatter;
34
import eu.etaxonomy.cdm.format.reference.ReferenceEllypsisFormatter.LabelType;
35
import eu.etaxonomy.cdm.model.agent.AgentBase;
36
import eu.etaxonomy.cdm.model.agent.Person;
37
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
38
import eu.etaxonomy.cdm.model.common.AnnotationType;
39
import eu.etaxonomy.cdm.model.common.CdmBase;
40
import eu.etaxonomy.cdm.model.common.Language;
41
import eu.etaxonomy.cdm.model.name.NomenclaturalCodeEdition;
42
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
43
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
44
import eu.etaxonomy.cdm.model.name.Rank;
45
import eu.etaxonomy.cdm.model.name.TaxonName;
46
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
47
import eu.etaxonomy.cdm.model.permission.CRUD;
48
import eu.etaxonomy.cdm.model.reference.Reference;
49
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
50
import eu.etaxonomy.cdm.model.reference.ReferenceType;
51
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
52
import eu.etaxonomy.cdm.model.term.TermType;
53
import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
54
import eu.etaxonomy.cdm.persistence.dao.common.Restriction.Operator;
55
import eu.etaxonomy.cdm.persistence.dao.initializer.EntityInitStrategy;
56
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
57
import eu.etaxonomy.cdm.service.TaxonNameStringFilterablePagingProvider;
58
import eu.etaxonomy.cdm.service.UserHelperAccess;
59
import eu.etaxonomy.cdm.service.initstrategies.AgentBaseInit;
60
import eu.etaxonomy.cdm.vaadin.event.EditorActionTypeFilter;
61
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
62
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
63
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
64
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorActionStrRep;
65
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityButtonUpdater;
66
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityReloader;
67
import eu.etaxonomy.cdm.vaadin.model.name.TaxonNameDTO;
68
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
69
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
70
import eu.etaxonomy.cdm.vaadin.util.ReferenceEllypsisCaptionGenerator;
71
import eu.etaxonomy.cdm.vaadin.view.reference.ReferencePopupEditor;
72
import eu.etaxonomy.cdm.vaadin.view.reference.RegistrationUiReferenceEditorFormConfigurator;
73
import eu.etaxonomy.vaadin.component.CompositeCustomField;
74
import eu.etaxonomy.vaadin.component.ReloadableLazyComboBox;
75
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
76
import eu.etaxonomy.vaadin.component.WeaklyRelatedEntityCombobox;
77
import eu.etaxonomy.vaadin.component.WeaklyRelatedEntityField;
78
import eu.etaxonomy.vaadin.event.FieldReplaceEvent;
79
import eu.etaxonomy.vaadin.mvp.AbstractCdmDTOEditorPresenter;
80
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
81
import eu.etaxonomy.vaadin.mvp.BeanInstantiator;
82
import eu.etaxonomy.vaadin.mvp.BoundField;
83
import eu.etaxonomy.vaadin.ui.view.PopupView;
84
import eu.etaxonomy.vaadin.util.PropertyIdPath;
85

    
86
/**
87
 * @author a.kohlbecker
88
 * @since May 22, 2017
89
 *
90
 */
91
@SpringComponent
92
@Scope("prototype")
93
public class TaxonNameEditorPresenter extends AbstractCdmDTOEditorPresenter<TaxonNameDTO, TaxonName, TaxonNamePopupEditorView> {
94

    
95
    private static final long serialVersionUID = -3538980627079389221L;
96

    
97
    private static final EnumSet<CRUD> SUB_EDITOR_CRUD = EnumSet.of(CRUD.UPDATE, CRUD.DELETE);
98

    
99
    private static final List<String> RELATED_NAME_INIT_STRATEGY = Arrays.asList(
100
            "$",
101
            "relationsFromThisName",
102
            "relationsToThisName.type",
103
            "homotypicalGroup.typifiedNames"
104
            );
105

    
106
    public static List<String> REFERENCE_INIT_STRATEGY = ReferenceEllypsisFormatter.INIT_STRATEGY;
107

    
108

    
109
    private static final Logger logger = Logger.getLogger(TaxonNameEditorPresenter.class);
110

    
111
    private CdmFilterablePagingProvider<Reference, Reference> nomReferencePagingProvider;
112

    
113
    private Reference publishedUnit;
114

    
115
    private BeanInstantiator<Reference> newReferenceInstantiator;
116

    
117
    private Map<ReferencePopupEditor, NomenclaturalStatusRow> statusTypeReferencePopupEditorsRowMap = new HashMap<>();
118

    
119
    private TaxonNameStringFilterablePagingProvider genusOrUninomialPartPagingProvider;
120

    
121
    private TaxonNameStringFilterablePagingProvider specificEpithetPartPagingProvider;
122

    
123
    private Property.ValueChangeListener refreshSpecificEpithetComboBoxListener;
124

    
125
    private CdmFilterablePagingProvider<TaxonName, TaxonName> relatedNamePagingProvider;
126

    
127
    private CdmFilterablePagingProvider<TaxonName, TaxonName> orthographicVariantNamePagingProvider;
128

    
129
    private Restriction<Reference> orthographicCorrectionRestriction;
130

    
131
    private Integer taxonNameId;
132

    
133
    /**
134
     * {@inheritDoc}
135
     */
136
    @SuppressWarnings("serial")
137
    @Override
138
    public void handleViewEntered() {
139

    
140
        super.handleViewEntered();
141

    
142
        List<NomenclaturalCodeEdition> nomCodes = NomenclaturalCodeEdition.forCode(RegistrationUIDefaults.NOMENCLATURAL_CODE);
143
        BeanItemContainer<NomenclaturalCodeEdition> codeEditionItemContainer = cdmBeanItemContainerFactory.buildEnumTermItemContainer(
144
                NomenclaturalCodeEdition.class, nomCodes.toArray(new NomenclaturalCodeEdition[nomCodes.size()])
145
                );
146

    
147
        getView().getRankSelect().setContainerDataSource(cdmBeanItemContainerFactory.buildBeanItemContainer(TermType.Rank));
148
        getView().getRankSelect().setItemCaptionPropertyId("label");
149

    
150
        CdmFilterablePagingProvider<AgentBase, TeamOrPersonBase> termOrPersonPagingProvider = pagingProviderFactory.teamOrPersonPagingProvider();
151
        termOrPersonPagingProvider.setInitStrategy(AgentBaseInit.TEAM_OR_PERSON_INIT_STRATEGY);
152
        CdmFilterablePagingProvider<AgentBase, Person> personPagingProvider = pagingProviderFactory.personPagingProvider();
153

    
154
        getView().getCombinationAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
155
        getView().getCombinationAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
156

    
157
        getView().getExCombinationAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
158
        getView().getExCombinationAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
159

    
160
        getView().getBasionymAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
161
        getView().getBasionymAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
162

    
163
        getView().getExBasionymAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
164
        getView().getExBasionymAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
165

    
166
        nomReferencePagingProvider = pagingProviderFactory.referencePagingProvider();
167
        nomReferencePagingProvider.setInitStrategy(REFERENCE_INIT_STRATEGY);
168
        getView().getNomReferenceCombobox().loadFrom(nomReferencePagingProvider, nomReferencePagingProvider, nomReferencePagingProvider.getPageSize());
169
        getView().getNomReferenceCombobox().setNestedButtonStateUpdater(new ToOneRelatedEntityButtonUpdater<Reference>(getView().getNomReferenceCombobox()));
170
        getView().getNomReferenceCombobox().getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.NOMENCLATURAL, getView().getNomReferenceCombobox().getSelect()));
171
        getView().getNomReferenceCombobox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getNomReferenceCombobox(), this));
172
        getView().getNomReferenceCombobox().getSelect().addValueChangeListener( e -> updateOrthographicCorrectionRestriction());
173

    
174
        CdmFilterablePagingProvider<Reference, Reference> icbnCodesPagingProvider = pagingProviderFactory.referencePagingProvider();
175
        // @formatter:off
176
        // TODO use markers on references instead of isbn. The marker type MarkerType.NOMENCLATURAL_RELEVANT() has already prepared (#7466)
177
        icbnCodesPagingProvider.getCriteria().add(Restrictions.in("isbn", new String[]{
178
                "3-904144-22-7",     // Saint Louis Code
179
                "3-906166-48-1",     // Vienna Code
180
                "978-3-87429-425-6", // Melbourne Code
181
                "978-3-946583-16-5", // Shenzhen Code
182
                "0-85301-006-4"      // ICZN 1999
183
                // ICNB
184
        }));
185
        // @formatter:on
186

    
187
        statusTypeReferencePopupEditorsRowMap.clear();
188
        getView().getNomStatusCollectionField().addElementAddedListener(e -> addNomenclaturalStatus(e.getElement()));
189
        getView().getNomStatusCollectionField().setEditorInstantiator(new AbstractElementCollection.Instantiator<NomenclaturalStatusRow>() {
190

    
191
            @Override
192
            public NomenclaturalStatusRow create() {
193
                NomenclaturalStatusRow row = new NomenclaturalStatusRow();
194

    
195
                BeanItemContainer<DefinedTermBase> statusTypeItemContainer = cdmBeanItemContainerFactory.buildBeanItemContainer(NomenclaturalStatusType.ALTERNATIVE().getVocabulary().getUuid());
196
                row.type.setContainerDataSource(statusTypeItemContainer);
197
                row.type.setItemCaptionMode(ItemCaptionMode.EXPLICIT);
198
                for(DefinedTermBase term : statusTypeItemContainer.getItemIds()){
199
                    row.type.setItemCaption(term, term.getPreferredRepresentation(Language.DEFAULT()).getAbbreviatedLabel());
200
                }
201
                row.type.setNullSelectionAllowed(false);
202

    
203
                row.citation.loadFrom(icbnCodesPagingProvider, icbnCodesPagingProvider, icbnCodesPagingProvider.getPageSize());
204
                row.citation.getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.NOMENCLATURAL, row.citation.getSelect()));
205
                row.citation.getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<Reference>(row.citation.getSelect(),
206
                        TaxonNameEditorPresenter.this));
207
                row.citation.addClickListenerAddEntity(e -> doReferenceEditorAdd(row));
208
                row.citation.addClickListenerEditEntity(e -> {
209
                    if(row.citation.getValue() != null){
210
                        doReferenceEditorEdit(row);
211
                    }
212
                });
213
                row.codeEdition.setContainerDataSource(codeEditionItemContainer);
214

    
215
                getView().applyDefaultComponentStyle(row.components());
216

    
217
                return row;
218
            }
219
        });
220

    
221

    
222
        relatedNamePagingProvider = pagingProviderFactory.taxonNamesWithoutOrthophicIncorrect();
223
        relatedNamePagingProvider.setInitStrategy(RELATED_NAME_INIT_STRATEGY);
224
        getView().getBasionymComboboxSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
225
        getView().getBasionymComboboxSelect().setPagingProviders(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize(), this);
226

    
227
        getView().getReplacedSynonymsComboboxSelect().setCaptionGenerator( new CdmTitleCacheCaptionGenerator<TaxonName>());
228
        getView().getReplacedSynonymsComboboxSelect().setPagingProviders(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize(), this);
229

    
230
        getView().getValidationField().getRelatedNameComboBox().getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
231
        getView().getValidationField().getRelatedNameComboBox().loadFrom(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize());
232
        getView().getValidationField().getRelatedNameComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getValidationField().getRelatedNameComboBox(), this));
233
        getView().getValidationField().getCitatonComboBox().getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.BIBLIOGRAPHIC, getView().getValidationField().getCitatonComboBox().getSelect()));
234
        getView().getValidationField().getCitatonComboBox().loadFrom(icbnCodesPagingProvider, icbnCodesPagingProvider, icbnCodesPagingProvider.getPageSize());
235
        getView().getValidationField().getCitatonComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getValidationField().getCitatonComboBox(), this));
236
        getView().getValidationField().getCodeEditionSelect().setContainerDataSource(codeEditionItemContainer);
237

    
238
        getView().getOrthographicVariantField().getRelatedNameComboBox().getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
239
        getView().getOrthographicVariantField().getRelatedNameComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getOrthographicVariantField().getRelatedNameComboBox(), this));
240
        getView().getOrthographicVariantField().getRelatedNameComboBox().loadFrom(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize());
241
        // The Mode TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION will be handled in the updateOrthographicCorrectionRestriction() method
242
        getView().getOrthographicVariantField().getCitatonComboBox().getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.BIBLIOGRAPHIC, getView().getOrthographicVariantField().getCitatonComboBox().getSelect()));
243
        getView().getOrthographicVariantField().getCitatonComboBox().loadFrom(icbnCodesPagingProvider, icbnCodesPagingProvider, icbnCodesPagingProvider.getPageSize());
244
        getView().getOrthographicVariantField().getCitatonComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getOrthographicVariantField().getCitatonComboBox(), this));
245
        getView().getOrthographicVariantField().getCodeEditionSelect().setContainerDataSource(codeEditionItemContainer);
246

    
247
        getView().getAnnotationsField().setAnnotationTypeItemContainer(cdmBeanItemContainerFactory.buildBeanItemContainer(
248
                AnnotationType.EDITORIAL().getVocabulary().getUuid()));
249
    }
250

    
251
    /**
252
     * @param element
253
     * @return
254
     */
255
    private void addNomenclaturalStatus(NomenclaturalStatus element) {
256
        // Nothing to do
257
    }
258

    
259
    @Override
260
    protected void adaptDataProviders() {
261
        updateOrthographicCorrectionRestriction();
262
    }
263

    
264
    private void updateOrthographicCorrectionRestriction() {
265

    
266
        if(getView().isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
267
            if(orthographicVariantNamePagingProvider == null){
268
                orthographicVariantNamePagingProvider = new CdmFilterablePagingProvider<TaxonName, TaxonName>(getRepo().getNameService());
269
                orthographicVariantNamePagingProvider.setInitStrategy(RELATED_NAME_INIT_STRATEGY);
270
                orthographicVariantNamePagingProvider.addRestriction(new Restriction<>("id", Operator.AND_NOT, null, taxonNameId));
271
                getView().getOrthographicVariantField().getRelatedNameComboBox().loadFrom(orthographicVariantNamePagingProvider, orthographicVariantNamePagingProvider, orthographicVariantNamePagingProvider.getPageSize());
272
            }
273
            Reference nomReference = getView().getNomReferenceCombobox().getValue();
274
            if(nomReference == null && orthographicCorrectionRestriction != null){
275
                orthographicVariantNamePagingProvider.getRestrictions().remove(orthographicCorrectionRestriction);
276
            } else {
277
                if(orthographicCorrectionRestriction == null){
278
                    orthographicCorrectionRestriction = new Restriction<>("nomenclaturalSource.citation", Operator.AND, null, nomReference);
279
                    orthographicVariantNamePagingProvider.addRestriction(orthographicCorrectionRestriction);
280
                } else{
281
                    orthographicCorrectionRestriction.setValues(Arrays.asList(nomReference));
282
                }
283
            }
284
            getView().getOrthographicVariantField().getRelatedNameComboBox().getSelect().refresh();
285
        }
286
    }
287

    
288
    @Override
289
    protected TaxonName loadCdmEntity(UUID identifier) {
290

    
291
        EntityInitStrategy initStrategy = new EntityInitStrategy(
292
                Arrays.asList(
293
                "$",
294
                "annotations.type",
295
                "annotations.*", // needed as log as we are using a table in FilterableAnnotationsField
296
                "rank.vocabulary", // needed for comparing ranks
297

    
298
                "nomenclaturalSource.citation",
299

    
300
                "status.type",
301
                "status.citation",
302

    
303
                "combinationAuthorship",
304
                "exCombinationAuthorship",
305
                "basionymAuthorship",
306
                "exBasionymAuthorship",
307

    
308
                // basionyms: relationsToThisName.fromName
309
                "relationsToThisName.type",
310
                "relationsToThisName.fromName.rank",
311
                "relationsToThisName.fromName.combinationAuthorship",
312
                "relationsToThisName.fromName.exCombinationAuthorship",
313
                "relationsToThisName.fromName.nomenclaturalSource.citation.authorship",
314
                "relationsToThisName.fromName.nomenclaturalSource.citation.inReference.authorship",
315
                "relationsToThisName.fromName.nomenclaturalSource.citation.inReference.inReference.inReference.authorship",
316
                "relationsToThisName.fromName.relationsToThisName",
317
                "relationsToThisName.fromName.relationsFromThisName",
318
                "relationsToThisName.citation",
319
                "relationsFromThisName",
320
                "homotypicalGroup.typifiedNames"
321
                )
322
              );
323
        initStrategy.extend("nomenclaturalSource.citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
324
        initStrategy.extend("status.citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
325
        initStrategy.extend("relationsToThisName.citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
326

    
327
        TaxonName taxonName;
328
        if(identifier != null){
329
            taxonName = getRepo().getNameService().load(identifier, initStrategy.getPropertyPaths());
330
        } else {
331
            taxonName = createCdmEntity();
332
        }
333

    
334
        if(getView().isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY)){
335
            Reference nomRef = taxonName.getNomenclaturalReference();
336

    
337
            //getView().getNomReferenceCombobox().setEnabled(nomRef.isOfType(ReferenceType.Section));
338
            publishedUnit = nomRef;
339
            if(publishedUnit != null){
340
                while(publishedUnit.isOfType(ReferenceType.Section) && publishedUnit.getInReference() != null){
341
                    publishedUnit = nomRef.getInReference();
342
                }
343
                // reduce available references to those which are sections of the publishedUnit and the publishedUnit itself
344
                // nomReferencePagingProvider
345
                nomReferencePagingProvider.getCriteria().add(Restrictions.or(
346
                        Restrictions.and(Restrictions.eq("inReference", publishedUnit), Restrictions.eq("type", ReferenceType.Section)),
347
                        Restrictions.idEq(publishedUnit.getId())
348
                        )
349
                );
350
            }
351
            // and remove the empty option
352
            getView().getNomReferenceCombobox().getSelect().setNullSelectionAllowed(false);
353

    
354
            // new Reference only a sub sections of the publishedUnit
355
            newReferenceInstantiator = new BeanInstantiator<Reference>() {
356
                @Override
357
                public Reference createNewBean() {
358
                    Reference newRef = ReferenceFactory.newSection();
359
                    newRef.setInReference(publishedUnit);
360
                    return newRef;
361
                }
362
            };
363

    
364
        }
365

    
366
        taxonNameId = Integer.valueOf(taxonName.getId());
367
        relatedNamePagingProvider.addRestriction(new Restriction<>("id", Operator.AND_NOT, null, taxonNameId));
368

    
369
        return taxonName;
370
    }
371

    
372
    /**
373
     * {@inheritDoc}
374
     */
375
    @Override
376
    protected void guaranteePerEntityCRUDPermissions(UUID identifier) {
377
        if(crud != null){
378
            newAuthorityCreated = UserHelperAccess.userHelper().createAuthorityForCurrentUser(TaxonName.class, identifier, crud, null);
379
        }
380

    
381
    }
382

    
383
    /**
384
     * {@inheritDoc}
385
     */
386
    @Override
387
    protected void guaranteePerEntityCRUDPermissions(TaxonName bean) {
388
        if(crud != null){
389
            newAuthorityCreated = UserHelperAccess.userHelper().createAuthorityForCurrentUser(bean, crud, null);
390
        }
391
    }
392

    
393
    /**
394
     * {@inheritDoc}
395
     */
396
    @Override
397
    protected INameService getService() {
398
        return getRepo().getNameService();
399
    }
400

    
401

    
402
    public void doReferenceEditorAdd(NomenclaturalStatusRow row) {
403

    
404
        ReferencePopupEditor referencePopupEditor = openPopupEditor(ReferencePopupEditor.class, null);
405

    
406
        referencePopupEditor.withReferenceTypes(RegistrationUIDefaults.MEDIA_REFERENCE_TYPES);
407
        referencePopupEditor.grantToCurrentUser(SUB_EDITOR_CRUD);
408
        referencePopupEditor.withDeleteButton(true);
409
        referencePopupEditor.loadInEditor(null);
410

    
411
        statusTypeReferencePopupEditorsRowMap.put(referencePopupEditor, row);
412
    }
413

    
414
    public void doReferenceEditorEdit(NomenclaturalStatusRow row) {
415

    
416
        ReferencePopupEditor referencePopupEditor = openPopupEditor(ReferencePopupEditor.class, null);
417
        referencePopupEditor.withReferenceTypes(RegistrationUIDefaults.MEDIA_REFERENCE_TYPES);
418
        referencePopupEditor.grantToCurrentUser(SUB_EDITOR_CRUD);
419
        referencePopupEditor.withDeleteButton(true);
420
        referencePopupEditor.loadInEditor(row.citation.getValue().getUuid());
421

    
422
        statusTypeReferencePopupEditorsRowMap.put(referencePopupEditor, row);
423
    }
424
    /**
425
     * @param referenceEditorPopup
426
     */
427
    private void configureReferencePopupEditor(ReferencePopupEditor referenceEditorPopup, UUID referenceUUID) {
428
        boolean nomRefSectionEditingOnly = getView().isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
429
        if(nomRefSectionEditingOnly){
430
            referenceEditorPopup.setBeanInstantiator(newReferenceInstantiator);
431
        }
432

    
433
        // TODO this should be configurable per UI - RegistrationUiReferenceEditorFormConfigurator as spring bean, different spring profiles
434
        referenceEditorPopup.setEditorComponentsConfigurator(new RegistrationUiReferenceEditorFormConfigurator(nomRefSectionEditingOnly && newReferenceInstantiator != null));
435

    
436
        referenceEditorPopup.loadInEditor(referenceUUID);
437
        if(!nomRefSectionEditingOnly){
438
            referenceEditorPopup.getTypeSelect().setValue(ReferenceType.Article);
439
        }
440
    }
441

    
442
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
443
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
444

    
445
        if(getView() == null || event.getSourceView() != getView() ){
446
            return;
447
        }
448

    
449
        ReferencePopupEditor referenceEditorPopup = openPopupEditor(ReferencePopupEditor.class, event);
450

    
451
        referenceEditorPopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
452
        referenceEditorPopup.withDeleteButton(true);
453
        configureReferencePopupEditor(referenceEditorPopup, null);
454
    }
455

    
456

    
457
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
458
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
459

    
460

    
461
        if(!isFromOwnView(event)){
462
            return;
463
        }
464
        ReferencePopupEditor referenceEditorPopup = openPopupEditor(ReferencePopupEditor.class, event);
465

    
466
        referenceEditorPopup.withDeleteButton(true);
467
        configureReferencePopupEditor(referenceEditorPopup, event.getEntityUuid());
468
    }
469

    
470
    @EventBusListenerMethod
471
    public void onFieldReplaceEvent(FieldReplaceEvent<String> event){
472

    
473
        PropertyIdPath boundPropertyIdPath = boundPropertyIdPath(event.getNewField());
474
        if(boundPropertyIdPath != null){
475
            TaxonNameDTO taxonNamedto = ((AbstractPopupEditor<TaxonNameDTO, AbstractCdmDTOEditorPresenter<TaxonNameDTO, TaxonName,?>>)getView()).getBean();
476
            if(boundPropertyIdPath.matches("specificEpithet")){
477
                AbstractField<String> genusOrUninomialField = getView().getGenusOrUninomialField();
478
                if(event.getNewField() instanceof CompositeCustomField){
479
                    if(specificEpithetPartPagingProvider == null){
480
                        specificEpithetPartPagingProvider = new TaxonNameStringFilterablePagingProvider(getRepo().getNameService(), Rank.SPECIES());
481
                    }
482
                    specificEpithetPartPagingProvider.listenToFields(
483
                            genusOrUninomialField,
484
                            null, null, null);
485
                    specificEpithetPartPagingProvider.excludeNames(taxonNamedto.cdmEntity());
486
                    specificEpithetPartPagingProvider.updateFromFields();
487
                    WeaklyRelatedEntityCombobox<TaxonName> specificEpithetField = (WeaklyRelatedEntityCombobox<TaxonName>)event.getNewField();
488
                    refreshSpecificEpithetComboBoxListener = e -> { specificEpithetField.getSelect().refresh(); specificEpithetField.setValue(null);};
489
                    specificEpithetField.loadFrom(specificEpithetPartPagingProvider, specificEpithetPartPagingProvider, specificEpithetPartPagingProvider.getPageSize());
490
                    specificEpithetField.setValue(event.getOldField().getValue());
491
                    specificEpithetField.reload();
492
                    genusOrUninomialField.addValueChangeListener(refreshSpecificEpithetComboBoxListener);
493
                } else {
494
                    if(specificEpithetPartPagingProvider != null){
495
                        specificEpithetPartPagingProvider.unlistenAllFields();
496
                    }
497
                    if(refreshSpecificEpithetComboBoxListener != null){
498
                        genusOrUninomialField.removeValueChangeListener(refreshSpecificEpithetComboBoxListener);
499
                        refreshSpecificEpithetComboBoxListener = null;
500
                    }
501
                }
502
            } else if(boundPropertyIdPath.matches("genusOrUninomial")) {
503
                if(event.getNewField() instanceof CompositeCustomField){
504
                    if(genusOrUninomialPartPagingProvider  == null){
505
                        genusOrUninomialPartPagingProvider = new TaxonNameStringFilterablePagingProvider(getRepo().getNameService());
506
                    }
507
                    genusOrUninomialPartPagingProvider.listenToFields(
508
                                null,
509
                                getView().getInfraGenericEpithetField(),
510
                                getView().getSpecificEpithetField(),
511
                                getView().getInfraSpecificEpithetField()
512
                               );
513
                    genusOrUninomialPartPagingProvider.excludeNames(taxonNamedto.cdmEntity());
514
                    WeaklyRelatedEntityCombobox<TaxonName> genusOrUninomialField = (WeaklyRelatedEntityCombobox<TaxonName>)event.getNewField();
515
                    genusOrUninomialField.loadFrom(genusOrUninomialPartPagingProvider, genusOrUninomialPartPagingProvider, genusOrUninomialPartPagingProvider.getPageSize());
516
                    genusOrUninomialField.setValue(event.getOldField().getValue());
517
                    genusOrUninomialField.reload();
518
                }else {
519
                    if(genusOrUninomialPartPagingProvider != null){
520
                        genusOrUninomialPartPagingProvider.unlistenAllFields();
521
                    }
522
                }
523

    
524
            }
525
        }
526

    
527
    }
528

    
529
    @EventBusListenerMethod
530
    public void onEntityChangeEvent(EntityChangeEvent<?> event){
531

    
532
        if(event.getSourceView() instanceof AbstractPopupEditor) {
533

    
534
            BoundField boundTargetField = boundTargetField((PopupView) event.getSourceView());
535

    
536
            if(boundTargetField != null){
537
                if(boundTargetField.matchesPropertyIdPath("genusOrUninomial")){
538
                    if(event.isCreateOrModifiedType()){
539
                        getCache().load(event.getEntity());
540
                        if(getView().getGenusOrUninomialField() instanceof WeaklyRelatedEntityCombobox){
541
                            WeaklyRelatedEntityCombobox<TaxonName> weaklyRelatedEntityCombobox = (WeaklyRelatedEntityCombobox<TaxonName>)getView().getGenusOrUninomialField();
542
                            weaklyRelatedEntityCombobox.setValue(((TaxonName)event.getEntity()).getGenusOrUninomial());
543
                            // NOTE: in contrast to the ToOneRelatedEntityCombobox the .discard() does not
544
                            // work here since no datasource is bound to the field, see weaklyRelatedEntityCombobox.reload()
545
                            weaklyRelatedEntityCombobox.updateButtons();
546
                        }
547
                    }
548
                } else
549
                if(boundTargetField.matchesPropertyIdPath("specificEpithet")){
550
                    if(event.isCreateOrModifiedType()){
551
                        getCache().load(event.getEntity());
552
                        if(getView().getSpecificEpithetField() instanceof WeaklyRelatedEntityCombobox){
553
                            WeaklyRelatedEntityCombobox<TaxonName> weaklyRelatedEntityCombobox = (WeaklyRelatedEntityCombobox<TaxonName>)getView().getSpecificEpithetField();
554
                            getView().getSpecificEpithetField().setValue(((TaxonName)event.getEntity()).getSpecificEpithet());
555
                            weaklyRelatedEntityCombobox.reload();
556
                            // NOTE: in contrast to the ToOneRelatedEntityCombobox the .discard() does not
557
                            // work here since no datasource is bound to the field, see weaklyRelatedEntityCombobox.reload()
558
                            weaklyRelatedEntityCombobox.updateButtons();
559
                        }
560
                    }
561
                } else
562
                if(boundTargetField.matchesPropertyIdPath("nomenclaturalSource.citation")){
563
                    if(event.isCreateOrModifiedType()){
564
                        getCache().load(event.getEntity());
565
                        if(event.isCreatedType()){
566
                            getView().getNomReferenceCombobox().setValue((Reference) event.getEntity());
567
                        } else {
568
                            getView().getNomReferenceCombobox().reload(); // refreshSelectedValue(modifiedReference);
569
                        }
570
                        getView().getCombinationAuthorshipField().discard(); //refresh from the datasource
571
                        getView().updateAuthorshipFields();
572
                    }
573
                } else
574
                if(boundTargetField.matchesPropertyIdPath("validationFor.otherName") || boundTargetField.matchesPropertyIdPath("orthographicVariant.otherName")){
575
                    ReloadableLazyComboBox<TaxonName> otherNameField = asReloadableLazyComboBox(boundTargetField.getField(TaxonName.class));
576
                    TaxonName otherName = (TaxonName) event.getEntity();
577
                    if(event.isCreateOrModifiedType()){
578
                        getCache().load(otherName);
579
                        if(event.isCreatedType()){
580
                            // TODO use reloadWith((TaxonName) event.getEntity()); also in this case?
581
                            otherNameField.setValue(otherName);
582
                        } else {
583
                            otherNameField.reloadWith(otherName);
584
                        }
585

    
586
                    } else
587
                    if(event.isRemovedType()){
588
                        otherNameField.setValue(null);
589
                    }
590
                } else
591
                if(boundTargetField.matchesPropertyIdPath("basionyms")){
592
                    ReloadableLazyComboBox<TaxonName> basionymSourceField = asReloadableLazyComboBox(boundTargetField.getField(TaxonName.class));
593
                    if(event.isCreateOrModifiedType()){
594
                        getCache().load(event.getEntity());
595
                        if(event.isCreatedType()){
596
                            // TODO use reloadWith((TaxonName) event.getEntity()); also in this case?
597
                            basionymSourceField .setValue((TaxonName) event.getEntity());
598
                        } else {
599
                            basionymSourceField.reloadWith((TaxonName) event.getEntity());
600
                        }
601
                        getView().getBasionymAuthorshipField().discard(); //refresh from the datasource
602
                        getView().getExBasionymAuthorshipField().discard(); //refresh from the datasource
603
                        getView().updateAuthorshipFields();
604
                    } else
605
                    if(event.isRemovedType()){
606
                        basionymSourceField.setValue(null);
607
                        getView().updateAuthorshipFields();
608
                    }
609
                } else
610
                if(boundTargetField.matchesPropertyIdPath("replacedSynonyms")){
611
                    ReloadableLazyComboBox<TaxonName> replacedSynonyms = asReloadableLazyComboBox(boundTargetField.getField(TaxonName.class));
612
                    if(event.isCreateOrModifiedType()){
613
                        getCache().load(event.getEntity());
614
                        if(event.isCreatedType()){
615
                            // TODO use reloadWith((TaxonName) event.getEntity()); also in this case?
616
                            replacedSynonyms .setValue((TaxonName) event.getEntity());
617
                        } else {
618
                            replacedSynonyms.reloadWith((TaxonName) event.getEntity());
619
                        }
620
                        getView().getExCombinationAuthorshipField().discard(); //refresh from the datasource
621
                        getView().updateAuthorshipFields();
622
                    } else
623
                    if(event.isRemovedType()){
624
                        replacedSynonyms.setValue(null);
625
                        getView().updateAuthorshipFields();
626
                    }
627
                }
628

    
629
            }
630
        }
631
    }
632

    
633
    protected <CDM extends CdmBase> ReloadableLazyComboBox<CDM> asReloadableLazyComboBox(Field<CDM> field){
634

    
635
        if(field instanceof ToOneRelatedEntityCombobox){
636
            field = ((ToOneRelatedEntityCombobox<CDM>)field).getSelect();
637
        }
638
        return (ReloadableLazyComboBox<CDM>)field;
639
    }
640

    
641

    
642

    
643
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
644
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
645

    
646
        if(getView() == null || event.getSourceView() != getView() ){
647
            return;
648
        }
649

    
650
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
651

    
652
        if(boundPropertyId != null){
653
            if(boundPropertyId.matches("validationFor.otherName") || boundPropertyId.matches("basionyms") || boundPropertyId.matches("replacedSynonyms")  || boundPropertyId.matches("orthographicVariant.otherName")){
654
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
655
                namePopup.withDeleteButton(true);
656
                getView().getModesActive().stream()
657
                    .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
658
                    .forEach(m -> namePopup.enableMode(m));
659
                if(boundPropertyId.matches("orthographicVariant.otherName") && getView().isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
660
                    namePopup.enableMode(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
661
                    namePopup.disableMode(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART);
662
                    namePopup.getOrthographicVariantToggle().setVisible(false);
663
                }
664
                namePopup.loadInEditor(event.getEntityUuid());
665
            }
666
        }
667
    }
668

    
669
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
670
    public void onTaxonNameEditorActionStrRepEdit(TaxonNameEditorActionStrRep event) {
671

    
672
        if(getView() == null || event.getSourceView() != getView() ){
673
            return;
674
        }
675

    
676
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
677

    
678
        if(boundPropertyId != null){
679
            if(boundPropertyId.matches("genusOrUninomial") || boundPropertyId.matches("specificEpithet")){
680
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
681
                namePopup.withDeleteButton(true);
682
                getView().getModesActive().stream()
683
                    .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
684
                    .forEach(m -> namePopup.enableMode(m));
685
                namePopup.loadInEditor(event.getEntityUuid());
686
            }
687
        }
688
    }
689

    
690
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
691
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
692

    
693
        if(getView() == null || event.getSourceView() != getView() ){
694
            return;
695
        }
696

    
697
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
698

    
699
        if(boundPropertyId != null){
700
            if(boundPropertyId.matches("validationFor.otherName") || boundPropertyId.matches("basionyms") || boundPropertyId.matches("replacedSynonyms") || boundPropertyId.matches("orthographicVariant.otherName")){
701
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
702
                namePopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
703
                namePopup.withDeleteButton(true);
704
                getView().getModesActive().stream()
705
                        .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
706
                        .forEach(m -> namePopup.enableMode(m));
707
                if(boundPropertyId.matches("orthographicVariant.otherName") && getView().isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
708
                    namePopup.enableMode(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
709
                    namePopup.disableMode(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART);
710
                    Reference nomrefPreset = (Reference)((AbstractPopupEditor<TaxonNameDTO, TaxonNameEditorPresenter>)getView()).getBean().getNomenclaturalReference();
711
                    namePopup.setCdmEntityInstantiator(new BeanInstantiator<TaxonName>() {
712

    
713
                        @Override
714
                        public TaxonName createNewBean() {
715
                            TaxonName newTaxonName = TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
716
                            newTaxonName.setNomenclaturalReference(getRepo().getReferenceService().load(nomrefPreset.getUuid(), TaxonNameEditorPresenter.REFERENCE_INIT_STRATEGY ));
717
                            return newTaxonName;
718
                        }
719
                    });
720
                    namePopup.getOrthographicVariantToggle().setVisible(false);
721
                }
722
                namePopup.loadInEditor(null);
723
            }
724
        }
725
    }
726

    
727
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
728
    public void onTaxonNameEditorActionStrRepAdd(TaxonNameEditorActionStrRep event) {
729

    
730
        if(getView() == null || event.getSourceView() != getView() ){
731
            return;
732
        }
733

    
734
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
735

    
736
        if(boundPropertyId != null){
737
            if(boundPropertyId.matches("genusOrUninomial") || boundPropertyId.matches("specificEpithet")){
738
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
739
                namePopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
740
                namePopup.withDeleteButton(true);
741
                getView().getModesActive().stream()
742
                .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
743
                .forEach(m -> namePopup.enableMode(m));
744
                namePopup.loadInEditor(null);
745
                if(boundPropertyId.matches("genusOrUninomial")){
746
                    namePopup.getRankSelect().setValue(Rank.GENUS());
747
                }
748
                if(boundPropertyId.matches("specificEpithet")){
749
                    namePopup.getGenusOrUninomialField().setValue(getView().getGenusOrUninomialField().getValue());
750
                    namePopup.getRankSelect().setValue(Rank.SPECIES());
751
                }
752
                if(WeaklyRelatedEntityField.class.isAssignableFrom(event.getTarget().getClass())){
753
                    WeaklyRelatedEntityField<TaxonName> taxoNameField = (WeaklyRelatedEntityField<TaxonName>)event.getTarget();
754
                    if(!taxoNameField.isValueInOptions()){
755
                        String nameString = event.getTarget().getValue();
756
                        if(StringUtils.isNotEmpty(nameString)){
757
                            if(boundPropertyId.matches("genusOrUninomial")){
758
                                namePopup.getGenusOrUninomialField().setValue(nameString);
759
                            }
760
                            if(boundPropertyId.matches("specificEpithet")){
761
                                namePopup.getSpecificEpithetField().setValue(nameString);
762
                            }
763
                        }
764
                    }
765
                }
766
            }
767
        }
768
    }
769

    
770
    /**
771
     * {@inheritDoc}
772
     */
773
    @Override
774
    protected TaxonNameDTO createDTODecorator(TaxonName cdmEntitiy) {
775
        return new TaxonNameDTO(cdmEntitiy);
776
    }
777

    
778
    /**
779
     * {@inheritDoc}
780
     */
781
    @Override
782
    protected BeanInstantiator<TaxonName> defaultCdmEntityInstantiator() {
783
        return new BeanInstantiator<TaxonName>() {
784

    
785
            @Override
786
            public TaxonName createNewBean() {
787
                return  TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
788
            }
789
        };
790
    }
791

    
792

    
793

    
794

    
795
}
(11-11/15)