Project

General

Profile

Download (37.5 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.Collection;
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.lang3.BooleanUtils;
19
import org.springframework.context.annotation.Scope;
20
import org.springframework.security.core.GrantedAuthority;
21

    
22
import com.vaadin.data.Property;
23
import com.vaadin.data.Property.ValueChangeListener;
24
import com.vaadin.spring.annotation.SpringComponent;
25
import com.vaadin.ui.AbstractField;
26
import com.vaadin.ui.Alignment;
27
import com.vaadin.ui.CheckBox;
28
import com.vaadin.ui.GridLayout;
29
import com.vaadin.ui.ListSelect;
30
import com.vaadin.ui.TextField;
31

    
32
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
33
import eu.etaxonomy.cdm.model.common.AnnotationType;
34
import eu.etaxonomy.cdm.model.common.CdmBase;
35
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
36
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
37
import eu.etaxonomy.cdm.model.name.Rank;
38
import eu.etaxonomy.cdm.model.name.TaxonName;
39
import eu.etaxonomy.cdm.model.reference.Reference;
40
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
41
import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
42
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
43
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
44
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
45
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorActionStrRep;
46
import eu.etaxonomy.cdm.vaadin.model.name.NameRelationshipDTO;
47
import eu.etaxonomy.cdm.vaadin.model.name.TaxonNameDTO;
48
import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
49
import eu.etaxonomy.cdm.vaadin.permission.CdmEditDeletePermissionTester;
50
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
51
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
52
import eu.etaxonomy.cdm.vaadin.util.converter.SetToListConverter;
53
import eu.etaxonomy.vaadin.component.NameRelationField;
54
import eu.etaxonomy.vaadin.component.ReloadableLazyComboBox;
55
import eu.etaxonomy.vaadin.component.SwitchableTextField;
56
import eu.etaxonomy.vaadin.component.ToManyRelatedEntitiesComboboxSelect;
57
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
58
import eu.etaxonomy.vaadin.component.WeaklyRelatedEntityCombobox;
59
import eu.etaxonomy.vaadin.event.EditorActionType;
60
import eu.etaxonomy.vaadin.mvp.AbstractCdmDTOPopupEditor;
61

    
62
/**
63
 * @author a.kohlbecker
64
 * @since May 22, 2017
65
 *
66
 */
67
@SpringComponent
68
@Scope("prototype")
69
public class TaxonNamePopupEditor extends AbstractCdmDTOPopupEditor<TaxonNameDTO, TaxonName, TaxonNameEditorPresenter>
70
    implements TaxonNamePopupEditorView, AccessRestrictedView{
71

    
72
    private static final long serialVersionUID = -7037436241474466359L;
73

    
74
    private final static int GRID_COLS = 4;
75

    
76
    private final static int GRID_ROWS = 18;
77

    
78
    private static final boolean HAS_BASIONYM_DEFAULT = false;
79

    
80
    private AbstractField<String> genusOrUninomialField;
81

    
82
    private AbstractField<String> infraGenericEpithetField;
83

    
84
    private AbstractField<String> specificEpithetField;
85

    
86
    private AbstractField<String> infraSpecificEpithetField;
87

    
88
    private SwitchableTextField fullTitleCacheFiled;
89

    
90
    private SwitchableTextField protectedNameCacheField;
91

    
92
    private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
93

    
94
    private TextField nomenclaturalReferenceDetail;
95

    
96
    private TeamOrPersonField exBasionymAuthorshipField;
97

    
98
    private TeamOrPersonField basionymAuthorshipField;
99

    
100
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
101

    
102
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> replacedSynonymsComboboxSelect;
103

    
104
    private NameRelationField validationField;
105

    
106
    private CheckBox basionymToggle;
107

    
108
    private CheckBox replacedSynonymsToggle;
109

    
110
    private CheckBox validationToggle;
111

    
112
    private ListSelect rankSelect;
113

    
114
    private TeamOrPersonField combinationAuthorshipField;
115

    
116
    private TeamOrPersonField exCombinationAuthorshipField;
117

    
118
    private EnumSet<TaxonNamePopupEditorMode> modesActive = EnumSet.noneOf(TaxonNamePopupEditorMode.class);
119

    
120
    private Boolean isInferredCombinationAuthorship = null;
121

    
122
    private Boolean isInferredBasionymAuthorship = null;
123

    
124
    private Boolean isInferredExBasionymAuthorship = null;
125

    
126
    private Map<AbstractField, Property.ValueChangeListener> authorshipUpdateListeners = new HashMap<>();
127

    
128
    private Boolean isInferredExCombinationAuthorship;
129

    
130
    private int specificEpithetFieldRow;
131

    
132
    private ValueChangeListener updateFieldVisibilityListener = e -> updateFieldVisibility();
133

    
134
    private FilterableAnnotationsField annotationsListField;
135

    
136
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
137

    
138
    private int genusOrUninomialRow;
139

    
140
    /**
141
     * By default  AnnotationType.EDITORIAL() is enabled.
142
     *
143
     * @return the editableAnotationTypes
144
     */
145
    @Override
146
    public AnnotationType[] getEditableAnotationTypes() {
147
        return editableAnotationTypes;
148
    }
149

    
150
    /**
151
     * By default  AnnotationType.EDITORIAL() is enabled.
152
     *
153
     *
154
     * @param editableAnotationTypes the editableAnotationTypes to set
155
     */
156
    @Override
157
    public void setEditableAnotationTypes(AnnotationType ... editableAnotationTypes) {
158
        this.editableAnotationTypes = editableAnotationTypes;
159
    }
160

    
161
    /**
162
     * @param layout
163
     * @param dtoType
164
     */
165
    public TaxonNamePopupEditor() {
166
        super(new GridLayout(GRID_COLS, GRID_ROWS), TaxonNameDTO.class);
167
    }
168

    
169
    /**
170
     * {@inheritDoc}
171
     */
172
    @Override
173
    public String getWindowCaption() {
174
        return "Name editor";
175
    }
176

    
177

    
178
    /**
179
     * {@inheritDoc}
180
     */
181
    @Override
182
    public int getWindowWidth() {
183
        return 800;
184
    }
185

    
186
    /**
187
     * {@inheritDoc}
188
     */
189
    @Override
190
    public void focusFirst() {
191
        // titleField.focus();
192

    
193
    }
194

    
195
    /**
196
     * {@inheritDoc}
197
     */
198
    @Override
199
    protected String getDefaultComponentStyles() {
200
        return "tiny";
201
    }
202

    
203
    /**
204
     * {@inheritDoc}
205
     */
206
    @Override
207
    protected void initContent() {
208

    
209
        GridLayout grid = (GridLayout)getFieldLayout();
210
        grid.setSizeFull();
211
        grid.setHideEmptyRowsAndColumns(true);
212
        grid.setSpacing(true);
213
        grid.setColumnExpandRatio(0, 0.3f);
214
        grid.setColumnExpandRatio(1, 0.3f);
215
        grid.setColumnExpandRatio(2, 0.3f);
216
        grid.setColumnExpandRatio(3, 0.0f);
217

    
218
        /*
219
         - nameType: preset, needs to be set in the presenter for new names
220
         - appendedPhrase: -> TODO field
221
         - nomenclaturalMicroReference:  -> TODO field
222
         - nomenclaturalReference ->  field but disabled for REGISTRY
223
         - rank -> SelectField which determines the visiblity of the other fields
224

    
225
         - fullTitleCache + protectedFullTitleCache -> SwitchableTextField : ADVANCED_MODE
226
         - nameCache + protectedNameCache -> SwitchableTextField : ADVANCED_MODE
227

    
228
         - homotypicalGroup -> hidden
229
         - typeDesignations -> hidden
230
         - descriptions -> hidden
231
         - taxonBases -> hidden
232
         - registrations -> hidden
233

    
234
         - relationsFromThisName-> TODO implement later
235
         - relationsToThisName -> TODO implement later
236

    
237
         - genusOrUninomial -> textField
238
         - infraGenericEpithet  -> textField
239
         - specificEpithet  -> textField
240
         - infraSpecificEpithet  -> textField
241

    
242
         - authorshipCache + protectedAuthorshipCache -> SwitchableTextField : only ADVANCED_MODE and disabled for REGISTRY
243
         - basionymAuthorship -> field but disabled for REGISTRY, basionym is set as nameRelationShip
244
         - combinationAuthorship -> field but disabled for REGISTRY author team of the reference
245
         - exCombinationAuthorship -> textField
246
         - exBasionymAuthorship -> textField
247

    
248
         - status -> TODO field
249
         - monomHybrid -> TODO implement hybrids later
250
         - binomHybrid -> TODO implement hybrids later
251
         - trinomHybrid -> TODO implement hybrids later
252

    
253
         - hybridParentRelations -> TODO implement hybrids later
254
         - hybridChildRelations -> TODO implement hybrids later
255
         - hybridFormula -> TODO implement hybrids later
256

    
257
         ** ViralName attributes **
258
         - acronym
259

    
260
         ** BacterialName attributes **
261
         - subGenusAuthorship
262
         - nameApprobation
263
         - breed
264
         - publicationYear
265
         - originalPublicationYear
266
         - cultivarName
267
        */
268

    
269
        int row = 0;
270

    
271
        rankSelect = new ListSelect("Rank");
272
        rankSelect.setNullSelectionAllowed(false);
273
        rankSelect.setRows(1);
274
        rankSelect.setWidth(100, Unit.PERCENTAGE);
275
        addField(rankSelect, "rank", 0, row, 1, row);
276
        grid.setComponentAlignment(rankSelect, Alignment.TOP_RIGHT);
277

    
278
        basionymToggle = new CheckBox("With basionym");
279
        basionymToggle.setValue(HAS_BASIONYM_DEFAULT);
280

    
281
        basionymToggle.setStyleName(getDefaultComponentStyles());
282
        grid.addComponent(basionymToggle, 2, row, 3, row);
283
        grid.setComponentAlignment(basionymToggle, Alignment.BOTTOM_LEFT);
284

    
285
        row++;
286
        replacedSynonymsToggle = new CheckBox("With replaced synonym");
287
        grid.addComponent(replacedSynonymsToggle, 2, row, 3, row);
288
        grid.setComponentAlignment(replacedSynonymsToggle, Alignment.BOTTOM_LEFT);
289

    
290
        row++;
291
        validationToggle = new CheckBox("Validation");
292

    
293
        grid.addComponent(validationToggle, 2, row, 3, row);
294
        grid.setComponentAlignment(validationToggle, Alignment.BOTTOM_LEFT);
295

    
296
        row++;
297
        // fullTitleCache
298
        fullTitleCacheFiled = addSwitchableTextField("Full title cache", "fullTitleCache", "protectedFullTitleCache", 0, row, GRID_COLS-1, row);
299
        fullTitleCacheFiled.setWidth(100, Unit.PERCENTAGE);
300
        row++;
301
        protectedNameCacheField = addSwitchableTextField("Name cache", "nameCache", "protectedNameCache", 0, row, GRID_COLS-1, row);
302
        protectedNameCacheField.setWidth(100, Unit.PERCENTAGE);
303
        row++;
304
        genusOrUninomialRow = row;
305
        genusOrUninomialField = addTextField("Genus or uninomial", "genusOrUninomial", 0, row, 1, row);
306
        genusOrUninomialField.setWidth(200, Unit.PIXELS);
307
        infraGenericEpithetField = addTextField("Infrageneric epithet", "infraGenericEpithet", 2, row, 3, row);
308
        infraGenericEpithetField.setWidth(200, Unit.PIXELS);
309
        row++;
310
        specificEpithetFieldRow = row;
311
        specificEpithetField = addTextField("Specific epithet", "specificEpithet", 0, row, 1, row);
312
        specificEpithetField.setWidth(200, Unit.PIXELS);
313
        infraSpecificEpithetField = addTextField("Infraspecific epithet", "infraSpecificEpithet", 2, row, 3, row);
314
        infraSpecificEpithetField.setWidth(200, Unit.PIXELS);
315

    
316
        row++;
317
        combinationAuthorshipField = new TeamOrPersonField("Combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
318
        combinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
319
        addField(combinationAuthorshipField, "combinationAuthorship", 0, row, GRID_COLS-1, row);
320

    
321
        row++;
322
        nomReferenceCombobox = new ToOneRelatedEntityCombobox<Reference>("Nomenclatural reference", Reference.class);
323
        nomReferenceCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
324
                this,
325
                new ReferenceEditorAction(EditorActionType.ADD, null, nomReferenceCombobox, this)
326
                ));
327
        nomReferenceCombobox.addClickListenerEditEntity(e -> {
328
            if(nomReferenceCombobox.getValue() != null){
329
                getViewEventBus().publish(this,
330
                    new ReferenceEditorAction(
331
                            EditorActionType.EDIT,
332
                            nomReferenceCombobox.getValue().getUuid(),
333
                            e.getButton(),
334
                            nomReferenceCombobox,
335
                            this)
336
                );
337
            }
338
            });
339

    
340

    
341
        // nomReferenceCombobox.getSelect().addValueChangeListener(e -> logger.debug("nomReferenceCombobox value changed #1"));
342
        // nomReferenceCombobox.setWidth(300, Unit.PIXELS);
343
        nomReferenceCombobox.setWidth("100%");
344
        addField(nomReferenceCombobox, "nomenclaturalReference", 0, row, 3, row);
345

    
346
        row++;
347
        nomenclaturalReferenceDetail = addTextField("Reference detail", "nomenclaturalMicroReference", 0, row, 2, row);
348
        nomenclaturalReferenceDetail.setWidth(100, Unit.PERCENTAGE);
349

    
350
        // --------------- Basionyms
351
        row++;
352
        basionymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Basionym");
353
        basionymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
354
        addField(basionymsComboboxSelect, "basionyms", 0, row, 3, row);
355
        basionymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
356
        basionymsComboboxSelect.withEditButton(true);
357
        basionymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
358
        basionymsComboboxSelect.setEditActionListener(e -> {
359

    
360
            Object fieldValue = e.getSource().getValue();
361
            UUID beanUuid = null;
362
            if(fieldValue != null){
363
                beanUuid = ((CdmBase)fieldValue).getUuid();
364

    
365
            }
366
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
367
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
368
        });
369
        grid.setComponentAlignment(basionymsComboboxSelect, Alignment.TOP_RIGHT);
370

    
371
        row++;
372
        basionymAuthorshipField = new TeamOrPersonField("Basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
373
        basionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
374
        addField(basionymAuthorshipField, "basionymAuthorship", 0, row, GRID_COLS-1, row);
375
        row++;
376
        exBasionymAuthorshipField = new TeamOrPersonField("Ex-basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
377
        exBasionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
378
        addField(exBasionymAuthorshipField, "exBasionymAuthorship", 0, row, GRID_COLS-1, row);
379

    
380
        // --------------- ReplacedSynonyms
381
        row++;
382
        replacedSynonymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Replaced synonyms");
383
        replacedSynonymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
384
        addField(replacedSynonymsComboboxSelect, "replacedSynonyms", 0, row, 3, row);
385
        replacedSynonymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
386
        replacedSynonymsComboboxSelect.withEditButton(true);
387
        replacedSynonymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
388
        replacedSynonymsComboboxSelect.setEditActionListener(e -> {
389

    
390
            Object fieldValue = e.getSource().getValue();
391
            UUID beanUuid = null;
392
            if(fieldValue != null){
393
                beanUuid = ((CdmBase)fieldValue).getUuid();
394

    
395
            }
396
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
397
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
398
        });
399
        grid.setComponentAlignment(replacedSynonymsComboboxSelect, Alignment.TOP_RIGHT);
400

    
401
        // --------------- Validation
402
        row++;
403
        validationField = new NameRelationField("Validation", Direction.relatedTo, NameRelationshipType.VALIDATED_BY_NAME());
404
        validationField.setWidth(100, Unit.PERCENTAGE);
405
        ToOneRelatedEntityCombobox<TaxonName> validatedNameComboBox = validationField.getValidatedNameComboBox();
406
        validatedNameComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
407
                this,
408
                new TaxonNameEditorAction(EditorActionType.ADD, null, validatedNameComboBox, this)
409
                ));
410
        validatedNameComboBox.addClickListenerEditEntity(e -> {
411
            if(validatedNameComboBox.getValue() != null){
412
                getViewEventBus().publish(this,
413
                    new TaxonNameEditorAction(
414
                            EditorActionType.EDIT,
415
                            validatedNameComboBox.getValue().getUuid(),
416
                            e.getButton(),
417
                            validatedNameComboBox,
418
                            this)
419
                );
420
            }
421
        });
422
        ToOneRelatedEntityCombobox<Reference> validationCitatonComboBox = validationField.getCitatonComboBox();
423
        validationCitatonComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
424
                this,
425
                new ReferenceEditorAction(EditorActionType.ADD, null, validationCitatonComboBox, this)
426
                ));
427
        validationCitatonComboBox.addClickListenerEditEntity(e -> {
428
            if(validationCitatonComboBox.getValue() != null){
429
                getViewEventBus().publish(this,
430
                    new ReferenceEditorAction(
431
                            EditorActionType.EDIT,
432
                            validationCitatonComboBox.getValue().getUuid(),
433
                            e.getButton(),
434
                            validationCitatonComboBox,
435
                            this)
436
                );
437
            }
438
        });
439
        addField(validationField, "validationFor", 0, row, 3, row);
440
        grid.setComponentAlignment(validationField, Alignment.TOP_RIGHT);
441

    
442
        row++;
443
        exCombinationAuthorshipField = new TeamOrPersonField("Ex-combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
444
        exCombinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
445
        addField(exCombinationAuthorshipField, "exCombinationAuthorship", 0, row, GRID_COLS-1, row);
446

    
447
        row++;
448
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
449
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
450
        annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
451
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
452

    
453
        // -----------------------------------------------------------------------------
454

    
455
        setAdvancedModeEnabled(true);
456
        registerAdvancedModeComponents(fullTitleCacheFiled, protectedNameCacheField);
457

    
458
        registerAdvancedModeComponents(combinationAuthorshipField);
459
        registerAdvancedModeComponents(basionymAuthorshipField);
460
        registerAdvancedModeComponents(exBasionymAuthorshipField);
461
        registerAdvancedModeComponents(exCombinationAuthorshipField);
462

    
463
        registerAdvancedModeComponents(combinationAuthorshipField.getCachFields());
464
        registerAdvancedModeComponents(exCombinationAuthorshipField.getCachFields());
465
        registerAdvancedModeComponents(basionymAuthorshipField.getCachFields());
466
        registerAdvancedModeComponents(exBasionymAuthorshipField.getCachFields());
467

    
468
        setAdvancedMode(false);
469

    
470
        //TODO remove below line once #7858 is fixed
471
        withDeleteButton(false);
472

    
473
    }
474

    
475
    protected TeamOrPersonBase inferBasiomynAuthors() {
476
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
477
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
478
            TaxonName basionym = basionyms.get(0);
479
            if(basionym.getCombinationAuthorship() != null){
480
                return basionym.getCombinationAuthorship();
481
            } else if(basionym.getNomenclaturalReference() != null){
482
                return basionym.getNomenclaturalReference().getAuthorship();
483
            }
484
        }
485
        return null;
486
    }
487

    
488
    protected TeamOrPersonBase inferExBasiomynAuthors() {
489
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
490
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
491
            TaxonName basionym = basionyms.get(0);
492
                return basionym.getExCombinationAuthorship();
493
        }
494
        return null;
495
    }
496

    
497
    protected TeamOrPersonBase inferCombinationAuthors() {
498
        Reference nomRef = nomReferenceCombobox.getValue();
499
        if(nomRef != null) {
500
            return nomRef.getAuthorship();
501
        }
502
        return null;
503
    }
504

    
505
    protected TeamOrPersonBase inferExCombinationAuthors() {
506
        NameRelationshipDTO nameRelationDTO = validationField.getValue();
507
        if(nameRelationDTO != null && nameRelationDTO.getOtherName() != null){
508
            TaxonName validatedName = nameRelationDTO.getOtherName();
509
            if(validatedName.getCombinationAuthorship() != null) {
510
                return validatedName.getCombinationAuthorship();
511
            } else if(validatedName.getNomenclaturalReference() != null){
512
                return validatedName.getNomenclaturalReference().getAuthorship();
513
            }
514
        }
515
        return null;
516
    }
517

    
518
    @Override
519
    protected void afterItemDataSourceSet() {
520

    
521

    
522
        rankSelect.addValueChangeListener(updateFieldVisibilityListener);
523
        basionymToggle.addValueChangeListener(e -> {
524
            updateAuthorshipFields();
525
        });
526
        validationToggle.addValueChangeListener(e -> {
527
            updateAuthorshipFields();
528
            });
529
        replacedSynonymsToggle.addValueChangeListener(e -> {
530
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
531
            replacedSynonymsComboboxSelect.setVisible(enable);
532
        });
533

    
534

    
535
        TaxonNameDTO taxonNameDTO = getBean();
536
        boolean showBasionymSection = taxonNameDTO.getBasionyms().size() > 0
537
                || taxonNameDTO.getBasionymAuthorship() != null
538
                || taxonNameDTO.getExBasionymAuthorship() != null;
539
        basionymToggle.setValue(showBasionymSection);
540
        basionymToggle.setReadOnly(showBasionymSection);
541

    
542
        boolean showReplacedSynonyms = taxonNameDTO.getReplacedSynonyms().size() > 0;
543
        replacedSynonymsToggle.setValue(showReplacedSynonyms);
544
        replacedSynonymsToggle.setReadOnly(showReplacedSynonyms);
545
        replacedSynonymsComboboxSelect.setVisible(showReplacedSynonyms);
546

    
547
        boolean showValidationSection = taxonNameDTO.getValidationFor() != null || taxonNameDTO.getExCombinationAuthorship() != null;
548

    
549
        validationToggle.setValue(showValidationSection);
550
        validationToggle.setReadOnly(showValidationSection);
551
//        validationField.setVisible(showValidation);
552
//        exCombinationAuthorshipField.setVisible(showExAuthors);
553

    
554
        if(isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
555
            updateAuthorshipFields();
556
        }
557
        if(isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY) && getBean().getNomenclaturalReference() != null) {
558
            nomReferenceCombobox.setDescription("Selection limited to nomenclatural reference and parts of it.");
559
        }
560
        if(isModeEnabled(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE)) {
561
            if(combinationAuthorshipField.getValue() == null){
562
                nomReferenceCombobox.setRequired(true);
563
            } else {
564
                combinationAuthorshipField.addValueChangeListener(e -> {
565
                    if(e.getProperty().getValue() == null){
566
                        nomReferenceCombobox.setRequired(true);
567
                    }
568
                });
569
            }
570
        }
571

    
572
    }
573

    
574
    /**
575
     * Updates all authorship fields if the an authorship field is empty this method attempts to infer the
576
     * authors from the related nomenclatural reference or taxon name.
577
     * <p>
578
     * Finally the {@link #updateFieldVisibility()} is invoked.
579
     *
580
     * @param taxonName
581
     */
582
    @Override
583
    public void updateAuthorshipFields() {
584

    
585
        TaxonNameDTO taxonName = getBean();
586

    
587
        // ------------- CombinationAuthors
588
        isInferredCombinationAuthorship = updateAuthorshipFieldData(
589
                taxonName.getCombinationAuthorship(),
590
                inferCombinationAuthors(),
591
                combinationAuthorshipField,
592
                nomReferenceCombobox.getSelect(),
593
                isInferredCombinationAuthorship);
594

    
595

    
596
        // ------------- Basionym and ExBasionymAuthors
597
        if(BooleanUtils.isTrue(basionymToggle.getValue())){
598

    
599
            isInferredBasionymAuthorship = updateAuthorshipFieldData(
600
                    taxonName.getBasionymAuthorship(),
601
                    inferBasiomynAuthors(),
602
                    basionymAuthorshipField,
603
                    basionymsComboboxSelect,
604
                    isInferredBasionymAuthorship
605
                    );
606

    
607
            isInferredExBasionymAuthorship = updateAuthorshipFieldData(
608
                    taxonName.getExBasionymAuthorship(),
609
                    inferExBasiomynAuthors(),
610
                    exBasionymAuthorshipField,
611
                    basionymsComboboxSelect,
612
                    isInferredExBasionymAuthorship
613
                    );
614

    
615
        }
616

    
617
        // ------------- Validation and ExCombinationAuthors
618
        isInferredExCombinationAuthorship = updateAuthorshipFieldData(
619
                taxonName.getExCombinationAuthorship(),
620
                inferExCombinationAuthors(),
621
                exCombinationAuthorshipField,
622
                validationField.getValidatedNameComboBox(),
623
                isInferredExCombinationAuthorship
624
                );
625

    
626
        updateFieldVisibility();
627

    
628
    }
629

    
630
//    /**
631
//     *
632
//     */
633
//    protected void updateAuthorshipFieldsVisibility() {
634
//        combinationAuthorshipField.setVisible(!isInferredCombinationAuthorship);
635
//        if(BooleanUtils.isTrue(basionymToggle.getValue())){
636
//            basionymAuthorshipField.setVisible(!isInferredBasionymAuthorship);
637
//            exBasionymAuthorshipField.setVisible(!isInferredExBasionymAuthorship);
638
//        }
639
//    }
640

    
641
    /**
642
     *
643
     * @param authorship
644
     *    the value of the taxonName authorship field
645
     * @param inferredAuthors
646
     *    the value inferred from other fields which may be set as authorship to the taxon name
647
     * @param authorshipField
648
     *    the ui element to edit the taxonName authorship field
649
     * @param updateTriggerField
650
     * @param lastInferredAuthorshipState
651
     * @return
652
     */
653
    protected Boolean updateAuthorshipFieldData(TeamOrPersonBase<?> authorship, TeamOrPersonBase inferredAuthors,
654
            TeamOrPersonField authorshipField, AbstractField updateTriggerField,
655
            Boolean lastInferredAuthorshipState) {
656

    
657
        if(authorship == null){
658
            authorshipField.setValue(inferredAuthors);
659
            lastInferredAuthorshipState = true;
660
        } else {
661
            boolean authorshipMatch = authorship == inferredAuthors;
662
            if(lastInferredAuthorshipState == null){
663
                // initialization of authorshipState, this comes only into account when the editor is just being initialized
664
                lastInferredAuthorshipState = authorshipMatch;
665
            }
666
            if(!authorshipMatch && lastInferredAuthorshipState){
667
                // update the combinationAuthorshipField to follow changes of the nomenclatural reference in case it was autofilled before
668
                authorshipField.setValue(inferredAuthors);
669
                lastInferredAuthorshipState = true;
670
            }
671
        }
672

    
673
        if(updateTriggerField != null){
674
            // IMPORTANT!
675
            // this ChangeListener must be added at this very late point in the editor lifecycle so that it is called after
676
            // the ToOneRelatedEntityReloader which may have been added to the updateTriggerField in the presenters handleViewEntered() method.
677
            // Otherwise we risk multiple representation problems in the hibernate session
678
            if(!authorshipUpdateListeners.containsKey(updateTriggerField)){
679
                ValueChangeListener listener = e ->  {
680
                    logger.debug(" value changed #2");
681
                    updateAuthorshipFields();
682
                };
683
                updateTriggerField.addValueChangeListener(listener);
684
                authorshipUpdateListeners.put(updateTriggerField, listener);
685
            }
686
        }
687

    
688
        return lastInferredAuthorshipState;
689
    }
690

    
691
    /**
692
     * @param rank
693
     * @return
694
     */
695
    private void updateFieldVisibility() {
696

    
697
        // TODO use getField() instead and remove field references
698
        Rank rank = (Rank) rankSelect.getValue();
699

    
700
        boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES());
701
        Boolean withBasionymSection = BooleanUtils.isTrue(basionymToggle.getValue());
702
        Boolean withValidationSection = BooleanUtils.isTrue(validationToggle.getValue());
703

    
704
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
705
            if(isSpeciesOrBelow) {
706
                if(TextField.class.isAssignableFrom(genusOrUninomialField.getClass())){
707
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
708
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
709
                            this,
710
                            new TaxonNameEditorActionStrRep(
711
                                    EditorActionType.ADD,
712
                                    e.getButton(),
713
                                    combobox,
714
                                    this)
715
                        ));
716
                    combobox.addClickListenerEditEntity(e -> {
717
                        if(combobox.getValue() != null){
718
                            getViewEventBus().publish(this,
719
                                new TaxonNameEditorActionStrRep(
720
                                        EditorActionType.EDIT,
721
                                        combobox.getIdForValue(),
722
                                        e.getButton(),
723
                                        combobox,
724
                                        this)
725
                            );
726
                        }
727
                    });
728
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, combobox, 0, genusOrUninomialRow, 1, genusOrUninomialRow);
729
                }
730
            } else {
731
                if(WeaklyRelatedEntityCombobox.class.isAssignableFrom(genusOrUninomialField.getClass())) {
732
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, new TextFieldNFix(), 0, genusOrUninomialRow, 1, genusOrUninomialRow);
733
                }
734
            }
735
        }
736

    
737
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
738
            if(rank.isInfraSpecific()) {
739
                if(TextField.class.isAssignableFrom(specificEpithetField.getClass())) {
740
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
741
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, combobox, 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
742
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
743
                            this,
744
                            new TaxonNameEditorActionStrRep(EditorActionType.ADD, e.getButton(), combobox, this)
745
                        ));
746
                    combobox.addClickListenerEditEntity(e -> {
747
                        if(combobox.getValue() != null){
748
                            getViewEventBus().publish(this,
749
                                new TaxonNameEditorActionStrRep(
750
                                        EditorActionType.EDIT,
751
                                        combobox.getIdForValue(),
752
                                        e.getButton(),
753
                                        combobox,
754
                                        this)
755
                            );
756
                        }
757
                    });
758
                }
759
            } else {
760
                if(WeaklyRelatedEntityCombobox.class.isAssignableFrom(specificEpithetField.getClass())) {
761
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, new TextFieldNFix(), 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
762
               }
763
            }
764
        }
765

    
766
        specificEpithetField.setVisible(isSpeciesOrBelow);
767
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
768
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
769

    
770
        basionymsComboboxSelect.setVisible(withBasionymSection);
771

    
772
        combinationAuthorshipField.setVisible(isInferredCombinationAuthorship != null && !isInferredCombinationAuthorship);
773
        basionymAuthorshipField.setVisible(withBasionymSection && isInferredBasionymAuthorship != null && !isInferredBasionymAuthorship);
774
        exBasionymAuthorshipField.setVisible(withBasionymSection && isInferredExBasionymAuthorship != null && !isInferredExBasionymAuthorship);
775

    
776
        validationField.setVisible(withValidationSection);
777
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
778

    
779

    
780
//        if(taxonName != null){
781
//            if(modesActive.contains(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
782
//            }
783
//        }
784

    
785
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
786
        specificEpithetField.setVisible(isSpeciesOrBelow);
787
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
788
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
789
    }
790

    
791

    
792
    @Override
793
    public void cancel() {
794
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
795
        rankSelect.removeValueChangeListener(updateFieldVisibilityListener);
796
        super.cancel();
797
    }
798

    
799
    /**
800
     * {@inheritDoc}
801
     */
802
    @Override
803
    public boolean allowAnonymousAccess() {
804
        return false;
805
    }
806

    
807
    /**
808
     * {@inheritDoc}
809
     */
810
    @Override
811
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
812
        return null;
813
    }
814

    
815
    /**
816
     * {@inheritDoc}
817
     */
818
    @Override
819
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
820
        return nomReferenceCombobox;
821
    }
822

    
823
    /**
824
     * {@inheritDoc}
825
     */
826
    @Override
827
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
828
        return basionymsComboboxSelect;
829
    }
830

    
831
    /**
832
     * {@inheritDoc}
833
     */
834
    @Override
835
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
836
        return replacedSynonymsComboboxSelect;
837
    }
838

    
839
    /**
840
     * {@inheritDoc}
841
     */
842
    @Override
843
    public ListSelect getRankSelect() {
844
        return rankSelect;
845
    }
846

    
847
    /**
848
     * {@inheritDoc}
849
     */
850
    @Override
851
    public AbstractField<String> getGenusOrUninomialField(){
852
        return genusOrUninomialField;
853
    }
854

    
855
    /**
856
     * @return the exBasionymAuthorshipField
857
     */
858
    @Override
859
    public TeamOrPersonField getExBasionymAuthorshipField() {
860
        return exBasionymAuthorshipField;
861
    }
862

    
863
    /**
864
     * @return the basionymAuthorshipField
865
     */
866
    @Override
867
    public TeamOrPersonField getBasionymAuthorshipField() {
868
        return basionymAuthorshipField;
869
    }
870

    
871
    /**
872
     * @return the combinationAuthorshipField
873
     */
874
    @Override
875
    public TeamOrPersonField getCombinationAuthorshipField() {
876
        return combinationAuthorshipField;
877
    }
878

    
879
    /**
880
     * @return the exCombinationAuthorshipField
881
     */
882
    @Override
883
    public TeamOrPersonField getExCombinationAuthorshipField() {
884
        return exCombinationAuthorshipField;
885
    }
886

    
887
    @Override
888
    public NameRelationField getValidationField(){
889
        return validationField;
890
    }
891

    
892
    @Override
893
    public void enableMode(TaxonNamePopupEditorMode mode){
894
            modesActive.add(mode);
895
    }
896

    
897
    @Override
898
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
899
        return modesActive.contains(mode);
900
    }
901

    
902
    @Override
903
    public void disableMode(TaxonNamePopupEditorMode mode){
904
        modesActive.remove(mode);
905
    }
906

    
907
    @Override
908
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
909
        return modesActive;
910
    }
911

    
912
    @Override
913
    public CheckBox getBasionymToggle() {
914
        return basionymToggle;
915
    }
916

    
917
    @Override
918
    public FilterableAnnotationsField getAnnotationsField() {
919
        return annotationsListField;
920
    }
921

    
922
    /**
923
     * {@inheritDoc}
924
     */
925
    @Override
926
    public void setReadOnly(boolean readOnly) {
927
        boolean basionymToggleReadonly = basionymToggle.isReadOnly();
928
        boolean validationToggleReadonly = validationToggle.isReadOnly();
929
        super.setReadOnly(readOnly);
930
        combinationAuthorshipField.setEditorReadOnly(readOnly);
931
        exCombinationAuthorshipField.setEditorReadOnly(readOnly);
932
        basionymAuthorshipField.setEditorReadOnly(readOnly);
933
        exBasionymAuthorshipField.setEditorReadOnly(readOnly);
934
        // preserve old readonly states if they were true
935
        if(basionymToggleReadonly){
936
            basionymToggle.setReadOnly(true);
937
        }
938
        if(validationToggleReadonly){
939
            validationToggle.setReadOnly(true);
940
        }
941
    }
942

    
943

    
944

    
945
    /**
946
     * @return the infraGenericEpithetField
947
     */
948
    @Override
949
    public AbstractField<String> getInfraGenericEpithetField() {
950
        return infraGenericEpithetField;
951
    }
952

    
953
    /**
954
     * @return the specificEpithetField
955
     */
956
    @Override
957
    public AbstractField<String> getSpecificEpithetField() {
958
        return specificEpithetField;
959
    }
960

    
961
    /**
962
     * @return the infraSpecificEpithetField
963
     */
964
    @Override
965
    public AbstractField<String> getInfraSpecificEpithetField() {
966
        return infraSpecificEpithetField;
967
    }
968

    
969

    
970
}
(10-10/13)