Project

General

Profile

Download (37.4 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
    }
471

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

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

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

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

    
515
    @Override
516
    protected void afterItemDataSourceSet() {
517

    
518

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

    
531

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

    
539
        boolean showReplacedSynonyms = taxonNameDTO.getReplacedSynonyms().size() > 0;
540
        replacedSynonymsToggle.setValue(showReplacedSynonyms);
541
        replacedSynonymsToggle.setReadOnly(showReplacedSynonyms);
542
        replacedSynonymsComboboxSelect.setVisible(showReplacedSynonyms);
543

    
544
        boolean showValidationSection = taxonNameDTO.getValidationFor() != null || taxonNameDTO.getExCombinationAuthorship() != null;
545

    
546
        validationToggle.setValue(showValidationSection);
547
        validationToggle.setReadOnly(showValidationSection);
548
//        validationField.setVisible(showValidation);
549
//        exCombinationAuthorshipField.setVisible(showExAuthors);
550

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

    
569
    }
570

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

    
582
        TaxonNameDTO taxonName = getBean();
583

    
584
        // ------------- CombinationAuthors
585
        isInferredCombinationAuthorship = updateAuthorshipFieldData(
586
                taxonName.getCombinationAuthorship(),
587
                inferCombinationAuthors(),
588
                combinationAuthorshipField,
589
                nomReferenceCombobox.getSelect(),
590
                isInferredCombinationAuthorship);
591

    
592

    
593
        // ------------- Basionym and ExBasionymAuthors
594
        if(BooleanUtils.isTrue(basionymToggle.getValue())){
595

    
596
            isInferredBasionymAuthorship = updateAuthorshipFieldData(
597
                    taxonName.getBasionymAuthorship(),
598
                    inferBasiomynAuthors(),
599
                    basionymAuthorshipField,
600
                    basionymsComboboxSelect,
601
                    isInferredBasionymAuthorship
602
                    );
603

    
604
            isInferredExBasionymAuthorship = updateAuthorshipFieldData(
605
                    taxonName.getExBasionymAuthorship(),
606
                    inferExBasiomynAuthors(),
607
                    exBasionymAuthorshipField,
608
                    basionymsComboboxSelect,
609
                    isInferredExBasionymAuthorship
610
                    );
611

    
612
        }
613

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

    
623
        updateFieldVisibility();
624

    
625
    }
626

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

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

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

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

    
685
        return lastInferredAuthorshipState;
686
    }
687

    
688
    /**
689
     * @param rank
690
     * @return
691
     */
692
    private void updateFieldVisibility() {
693

    
694
        // TODO use getField() instead and remove field references
695
        Rank rank = (Rank) rankSelect.getValue();
696

    
697
        boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES());
698
        Boolean withBasionymSection = BooleanUtils.isTrue(basionymToggle.getValue());
699
        Boolean withValidationSection = BooleanUtils.isTrue(validationToggle.getValue());
700

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

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

    
763
        specificEpithetField.setVisible(isSpeciesOrBelow);
764
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
765
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
766

    
767
        basionymsComboboxSelect.setVisible(withBasionymSection);
768

    
769
        combinationAuthorshipField.setVisible(isInferredCombinationAuthorship != null && !isInferredCombinationAuthorship);
770
        basionymAuthorshipField.setVisible(withBasionymSection && isInferredBasionymAuthorship != null && !isInferredBasionymAuthorship);
771
        exBasionymAuthorshipField.setVisible(withBasionymSection && isInferredExBasionymAuthorship != null && !isInferredExBasionymAuthorship);
772

    
773
        validationField.setVisible(withValidationSection);
774
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
775

    
776

    
777
//        if(taxonName != null){
778
//            if(modesActive.contains(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
779
//            }
780
//        }
781

    
782
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
783
        specificEpithetField.setVisible(isSpeciesOrBelow);
784
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
785
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
786
    }
787

    
788

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

    
796
    /**
797
     * {@inheritDoc}
798
     */
799
    @Override
800
    public boolean allowAnonymousAccess() {
801
        return false;
802
    }
803

    
804
    /**
805
     * {@inheritDoc}
806
     */
807
    @Override
808
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
809
        return null;
810
    }
811

    
812
    /**
813
     * {@inheritDoc}
814
     */
815
    @Override
816
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
817
        return nomReferenceCombobox;
818
    }
819

    
820
    /**
821
     * {@inheritDoc}
822
     */
823
    @Override
824
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
825
        return basionymsComboboxSelect;
826
    }
827

    
828
    /**
829
     * {@inheritDoc}
830
     */
831
    @Override
832
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
833
        return replacedSynonymsComboboxSelect;
834
    }
835

    
836
    /**
837
     * {@inheritDoc}
838
     */
839
    @Override
840
    public ListSelect getRankSelect() {
841
        return rankSelect;
842
    }
843

    
844
    /**
845
     * {@inheritDoc}
846
     */
847
    @Override
848
    public AbstractField<String> getGenusOrUninomialField(){
849
        return genusOrUninomialField;
850
    }
851

    
852
    /**
853
     * @return the exBasionymAuthorshipField
854
     */
855
    @Override
856
    public TeamOrPersonField getExBasionymAuthorshipField() {
857
        return exBasionymAuthorshipField;
858
    }
859

    
860
    /**
861
     * @return the basionymAuthorshipField
862
     */
863
    @Override
864
    public TeamOrPersonField getBasionymAuthorshipField() {
865
        return basionymAuthorshipField;
866
    }
867

    
868
    /**
869
     * @return the combinationAuthorshipField
870
     */
871
    @Override
872
    public TeamOrPersonField getCombinationAuthorshipField() {
873
        return combinationAuthorshipField;
874
    }
875

    
876
    /**
877
     * @return the exCombinationAuthorshipField
878
     */
879
    @Override
880
    public TeamOrPersonField getExCombinationAuthorshipField() {
881
        return exCombinationAuthorshipField;
882
    }
883

    
884
    @Override
885
    public NameRelationField getValidationField(){
886
        return validationField;
887
    }
888

    
889
    @Override
890
    public void enableMode(TaxonNamePopupEditorMode mode){
891
            modesActive.add(mode);
892
    }
893

    
894
    @Override
895
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
896
        return modesActive.contains(mode);
897
    }
898

    
899
    @Override
900
    public void disableMode(TaxonNamePopupEditorMode mode){
901
        modesActive.remove(mode);
902
    }
903

    
904
    @Override
905
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
906
        return modesActive;
907
    }
908

    
909
    @Override
910
    public CheckBox getBasionymToggle() {
911
        return basionymToggle;
912
    }
913

    
914
    @Override
915
    public FilterableAnnotationsField getAnnotationsField() {
916
        return annotationsListField;
917
    }
918

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

    
940

    
941

    
942
    /**
943
     * @return the infraGenericEpithetField
944
     */
945
    @Override
946
    public AbstractField<String> getInfraGenericEpithetField() {
947
        return infraGenericEpithetField;
948
    }
949

    
950
    /**
951
     * @return the specificEpithetField
952
     */
953
    @Override
954
    public AbstractField<String> getSpecificEpithetField() {
955
        return specificEpithetField;
956
    }
957

    
958
    /**
959
     * @return the infraSpecificEpithetField
960
     */
961
    @Override
962
    public AbstractField<String> getInfraSpecificEpithetField() {
963
        return infraSpecificEpithetField;
964
    }
965

    
966

    
967
}
(10-10/13)