Project

General

Profile

Download (48.7 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.vaadin.viritin.fields.AbstractElementCollection.Instantiator;
21
import org.vaadin.viritin.fields.ElementCollectionField;
22

    
23
import com.vaadin.data.Property;
24
import com.vaadin.data.Property.ValueChangeListener;
25
import com.vaadin.data.Validator.InvalidValueException;
26
import com.vaadin.server.ErrorMessage;
27
import com.vaadin.shared.ui.MarginInfo;
28
import com.vaadin.spring.annotation.SpringComponent;
29
import com.vaadin.ui.AbstractField;
30
import com.vaadin.ui.Alignment;
31
import com.vaadin.ui.CheckBox;
32
import com.vaadin.ui.Component;
33
import com.vaadin.ui.GridLayout;
34
import com.vaadin.ui.NativeSelect;
35
import com.vaadin.ui.Panel;
36
import com.vaadin.ui.TextField;
37

    
38
import eu.etaxonomy.cdm.api.utility.RoleProber;
39
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
40
import eu.etaxonomy.cdm.model.common.AnnotationType;
41
import eu.etaxonomy.cdm.model.common.CdmBase;
42
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
43
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
44
import eu.etaxonomy.cdm.model.name.Rank;
45
import eu.etaxonomy.cdm.model.name.RankClass;
46
import eu.etaxonomy.cdm.model.name.TaxonName;
47
import eu.etaxonomy.cdm.model.reference.Reference;
48
import eu.etaxonomy.cdm.service.UserHelperAccess;
49
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
50
import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
51
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
52
import eu.etaxonomy.cdm.vaadin.data.validator.NomenclaturalReferenceExistsValidator;
53
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
54
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
55
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorActionStrRep;
56
import eu.etaxonomy.cdm.vaadin.model.name.NameRelationshipDTO;
57
import eu.etaxonomy.cdm.vaadin.model.name.NomenclaturalStatusDTO;
58
import eu.etaxonomy.cdm.vaadin.model.name.TaxonNameDTO;
59
import eu.etaxonomy.cdm.vaadin.permission.CdmEditDeletePermissionTester;
60
import eu.etaxonomy.cdm.vaadin.permission.RolesAndPermissions;
61
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
62
import eu.etaxonomy.cdm.vaadin.ui.UIMessages;
63
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
64
import eu.etaxonomy.cdm.vaadin.util.converter.SetToListConverter;
65
import eu.etaxonomy.vaadin.component.NameRelationField;
66
import eu.etaxonomy.vaadin.component.ReloadableLazyComboBox;
67
import eu.etaxonomy.vaadin.component.SwitchableTextField;
68
import eu.etaxonomy.vaadin.component.ToManyRelatedEntitiesComboboxSelect;
69
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
70
import eu.etaxonomy.vaadin.component.WeaklyRelatedEntityCombobox;
71
import eu.etaxonomy.vaadin.event.EditorActionType;
72
import eu.etaxonomy.vaadin.mvp.AbstractCdmDTOPopupEditor;
73

    
74
/**
75
 * @author a.kohlbecker
76
 * @since May 22, 2017
77
 */
78
@SpringComponent
79
@Scope("prototype")
80
public class TaxonNamePopupEditor extends AbstractCdmDTOPopupEditor<TaxonNameDTO, TaxonName, TaxonNameEditorPresenter>
81
    implements TaxonNamePopupEditorView{
82

    
83
    private static final long serialVersionUID = -7037436241474466359L;
84

    
85
    private final static int GRID_COLS = 4;
86

    
87
    private final static int GRID_ROWS = 21;
88

    
89
    private static final boolean HAS_BASIONYM_DEFAULT = false;
90

    
91
    private AbstractField<String> genusOrUninomialField;
92

    
93
    private AbstractField<String> infraGenericEpithetField;
94

    
95
    private AbstractField<String> specificEpithetField;
96

    
97
    private AbstractField<String> infraSpecificEpithetField;
98

    
99
    private SwitchableTextField fullTitleCacheFiled;
100

    
101
    private SwitchableTextField protectedNameCacheField;
102

    
103
    private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
104

    
105
    private TextField nomenclaturalReferenceDetail;
106

    
107
    private TeamOrPersonField exBasionymAuthorshipField;
108

    
109
    private TeamOrPersonField basionymAuthorshipField;
110

    
111
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
112

    
113
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> replacedSynonymsComboboxSelect;
114

    
115
    private NameRelationField validationField;
116

    
117
    private NameRelationField orthographicVariantField;
118

    
119
    private CheckBox nomStatusCollectionFieldToggle;
120

    
121
    private ElementCollectionField<NomenclaturalStatusDTO> nomStatusCollectionField;
122

    
123
    private CheckBox basionymToggle;
124

    
125
    private CheckBox replacedSynonymsToggle;
126

    
127
    private CheckBox validationToggle;
128

    
129
    private CheckBox orthographicVariantToggle;
130

    
131
    private NativeSelect rankSelect;
132

    
133
    private TeamOrPersonField combinationAuthorshipField;
134

    
135
    private TeamOrPersonField exCombinationAuthorshipField;
136

    
137
    private EnumSet<TaxonNamePopupEditorMode> modesActive = EnumSet.noneOf(TaxonNamePopupEditorMode.class);
138

    
139
    private Boolean isInferredCombinationAuthorship = null;
140

    
141
    private Boolean isInferredBasionymAuthorship = null;
142

    
143
    private Boolean isInferredExBasionymAuthorship = null;
144

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

    
147
    private Boolean isInferredExCombinationAuthorship;
148

    
149
    private int specificEpithetFieldRow;
150

    
151
    private ValueChangeListener updateFieldVisibilityListener = e -> updateFieldVisibility();
152

    
153
    private FilterableAnnotationsField annotationsListField;
154

    
155
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
156

    
157
    private int genusOrUninomialRow;
158

    
159
    private OrthographicCorrectionReferenceValidator orthographicCorrectionValidator;
160

    
161
    /**
162
     * By default  AnnotationType.EDITORIAL() is enabled.
163
     *
164
     * @return the editableAnotationTypes
165
     */
166
    @Override
167
    public AnnotationType[] getEditableAnotationTypes() {
168
        return editableAnotationTypes;
169
    }
170

    
171
    /**
172
     * By default  AnnotationType.EDITORIAL() is enabled.
173
     *
174
     * @param editableAnotationTypes the editableAnotationTypes to set
175
     */
176
    @Override
177
    public void setEditableAnotationTypes(AnnotationType ... editableAnotationTypes) {
178
        this.editableAnotationTypes = editableAnotationTypes;
179
    }
180

    
181
    public TaxonNamePopupEditor() {
182
        super(new GridLayout(GRID_COLS, GRID_ROWS), TaxonNameDTO.class);
183
    }
184

    
185
    @Override
186
    public String getWindowCaption() {
187
        return "Name editor";
188
    }
189

    
190
    @Override
191
    public int getWindowWidth() {
192
        return 800;
193
    }
194

    
195
    @Override
196
    public void focusFirst() {
197
        // none
198
    }
199

    
200
    @Override
201
    public void applyDefaultComponentStyle(Component ... components){
202
        for(int i = 0; i <components.length; i++){
203
            components[i].setStyleName(getDefaultComponentStyles());
204
        }
205
    }
206

    
207
    @Override
208
    protected String getDefaultComponentStyles() {
209
        return "tiny";
210
    }
211

    
212
    @Override
213
    protected void initContent() {
214

    
215
        GridLayout grid = (GridLayout)getFieldLayout();
216
        grid.setSizeFull();
217
        grid.setHideEmptyRowsAndColumns(true);
218
        grid.setSpacing(true);
219
        grid.setColumnExpandRatio(0, 0.3f);
220
        grid.setColumnExpandRatio(1, 0.3f);
221
        grid.setColumnExpandRatio(2, 0.3f);
222
        grid.setColumnExpandRatio(3, 0.0f);
223

    
224
        /*
225
         * TaxonName properties for reference here (NOTE: this editor operates on TaxonNameDTOs!):
226
         - nameType: preset, needs to be set in the presenter for new names
227
         - appendedPhrase: -> TODO field
228
         - nomenclaturalMicroReference:  -> TODO field
229
         - nomenclaturalSource.citation ->  field but disabled for REGISTRY
230
         - rank -> SelectField which determines the visiblity of the other fields
231

    
232
         - fullTitleCache + protectedFullTitleCache -> SwitchableTextField : ADVANCED_MODE
233
         - nameCache + protectedNameCache -> SwitchableTextField : ADVANCED_MODE
234

    
235
         - homotypicalGroup -> hidden
236
         - typeDesignations -> hidden
237
         - descriptions -> hidden
238
         - taxonBases -> hidden
239
         - registrations -> hidden
240

    
241
         - relationsFromThisName-> TODO implement later
242
         - relationsToThisName -> TODO implement later
243

    
244
         - genusOrUninomial -> textField
245
         - infraGenericEpithet  -> textField
246
         - specificEpithet  -> textField
247
         - infraSpecificEpithet  -> textField
248

    
249
         - authorshipCache + protectedAuthorshipCache -> SwitchableTextField : only ADVANCED_MODE and disabled for REGISTRY
250
         - basionymAuthorship -> field but disabled for REGISTRY, basionym is set as nameRelationShip
251
         - combinationAuthorship -> field but disabled for REGISTRY author team of the reference
252
         - exCombinationAuthorship -> textField
253
         - exBasionymAuthorship -> textField
254

    
255
         - status -> TODO field
256
         - monomHybrid -> TODO implement hybrids later
257
         - binomHybrid -> TODO implement hybrids later
258
         - trinomHybrid -> TODO implement hybrids later
259

    
260
         - hybridParentRelations -> TODO implement hybrids later
261
         - hybridChildRelations -> TODO implement hybrids later
262
         - hybridFormula -> TODO implement hybrids later
263

    
264
         ** ViralName attributes **
265
         - acronym
266

    
267
         ** BacterialName attributes **
268
         - subGenusAuthorship
269
         - nameApprobation
270
         - breed
271
         - publicationYear
272
         - originalPublicationYear
273
         - cultivarName
274
        */
275

    
276
        int row = 0;
277

    
278
        rankSelect = new NativeSelect("Rank");
279
        rankSelect.setNullSelectionAllowed(false);
280
        rankSelect.setWidth(100, Unit.PERCENTAGE);
281
        addField(rankSelect, "rank", 0, row, 1, row);
282
        grid.setComponentAlignment(rankSelect, Alignment.TOP_RIGHT);
283

    
284
        row++;
285
        basionymToggle = new CheckBox("With basionym");
286
        basionymToggle.setValue(HAS_BASIONYM_DEFAULT);
287
        basionymToggle.setStyleName(getDefaultComponentStyles());
288
        grid.addComponent(basionymToggle, 0, row);
289
        grid.setComponentAlignment(basionymToggle, Alignment.BOTTOM_LEFT);
290

    
291
        replacedSynonymsToggle = new CheckBox("With replaced synonym");
292
        grid.addComponent(replacedSynonymsToggle, 1, row);
293
        grid.setComponentAlignment(replacedSynonymsToggle, Alignment.BOTTOM_LEFT);
294

    
295
        validationToggle = new CheckBox("Validation");
296
        grid.addComponent(validationToggle, 2, row);
297
        grid.setComponentAlignment(validationToggle, Alignment.BOTTOM_LEFT);
298

    
299
        orthographicVariantToggle = new CheckBox("Orthographical variant");
300
        grid.addComponent(orthographicVariantToggle, 3, row);
301
        grid.setComponentAlignment(orthographicVariantToggle, Alignment.BOTTOM_LEFT);
302

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

    
323
        row++;
324
        combinationAuthorshipField = new TeamOrPersonField("Combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
325
        combinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
326
        addField(combinationAuthorshipField, "combinationAuthorship", 0, row, GRID_COLS-1, row);
327

    
328
        row++;
329
        nomReferenceCombobox = new ToOneRelatedEntityCombobox<Reference>("Nomenclatural reference", Reference.class);
330
        nomReferenceCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
331
                this,
332
                new ReferenceEditorAction(EditorActionType.ADD, null, nomReferenceCombobox, this)
333
                ));
334
        nomReferenceCombobox.addClickListenerEditEntity(e -> {
335
            if(nomReferenceCombobox.getValue() != null){
336
                getViewEventBus().publish(this,
337
                    new ReferenceEditorAction(
338
                            EditorActionType.EDIT,
339
                            nomReferenceCombobox.getValue().getUuid(),
340
                            e.getButton(),
341
                            nomReferenceCombobox,
342
                            this)
343
                );
344
            }
345
            });
346

    
347

    
348
        // nomReferenceCombobox.getSelect().addValueChangeListener(e -> logger.debug("nomReferenceCombobox value changed #1"));
349
        // nomReferenceCombobox.setWidth(300, Unit.PIXELS);
350
        nomReferenceCombobox.setWidth("100%");
351
        addField(nomReferenceCombobox, "nomenclaturalReference", 0, row, 3, row);
352

    
353
        row++;
354
        nomenclaturalReferenceDetail = addTextField("Reference detail", "nomenclaturalMicroReference", 0, row, 2, row);
355
        nomenclaturalReferenceDetail.setWidth(100, Unit.PERCENTAGE);
356

    
357
        // --------------- nom status
358
        row++;
359
        nomStatusCollectionFieldToggle = new CheckBox("Invalid, illegitimate, or other status");
360
        nomStatusCollectionFieldToggle.addValueChangeListener(e -> {
361
            nomStatusCollectionField.getLayout().getParent().setVisible(nomStatusCollectionFieldToggle.getValue());
362
        });
363
        addComponent(nomStatusCollectionFieldToggle, 0, row, 0, row);
364
        row++;
365
        nomStatusCollectionField = new ElementCollectionField<NomenclaturalStatusDTO>(
366
                NomenclaturalStatusDTO.class,
367
                new Instantiator<NomenclaturalStatusDTO>() {
368
                    private static final long serialVersionUID = -2427045940046513092L;
369

    
370
                    @Override
371
                    public NomenclaturalStatusDTO create() {
372
                        return NomenclaturalStatusDTO.newInstance();
373
                    }
374
                },
375
                NomenclaturalStatusRow.class
376
                ){
377
                    private static final long serialVersionUID = -3130918034491809593L;
378

    
379
                    @Override
380
                    public void commit() throws SourceException, InvalidValueException {
381
                        validate(); // validate always so that empty rows are recognized
382
                        super.commit();
383
                    }
384

    
385
                    @Override
386
                    public boolean isEmpty() {
387
                        Collection<?> value = getValue();
388
                        return value == null || value.isEmpty() ;
389
                    }
390

    
391
                    @Override
392
                    public void setComponentError(ErrorMessage componentError) {
393
                        nomStatusCollectionField.setComponentError(componentError);
394
                    }
395

    
396
        };
397

    
398
        nomStatusCollectionField.getLayout().setSpacing(false);
399
        nomStatusCollectionField.setVisibleProperties(NomenclaturalStatusRow.visibleFields());
400
        nomStatusCollectionField.setPropertyHeader("type", "Status type");
401
        nomStatusCollectionField.setPropertyHeader("citation", "Reference");
402
        nomStatusCollectionField.setPropertyHeader("citationMicroReference", "Reference detail");
403
        nomStatusCollectionField.setPropertyHeader("ruleConsidered", "Rule considered");
404
        nomStatusCollectionField.addElementAddedListener( e -> nomStatusCollectionField.setComponentError(null));
405
        nomStatusCollectionField.getLayout().setMargin(new MarginInfo(false, true));
406

    
407
        Panel nomStatusCollectionPanel = new Panel(nomStatusCollectionField.getLayout());
408
        nomStatusCollectionPanel.setCaption("Status");
409
        nomStatusCollectionPanel.setWidth(100, Unit.PERCENTAGE);
410

    
411
        bindField(nomStatusCollectionField, "status");
412
        addComponent(nomStatusCollectionPanel, 0, row, 3, row);
413

    
414
        // --------------- Basionyms
415
        row++;
416
        basionymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Basionym");
417
        basionymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
418
        addField(basionymsComboboxSelect, "basionyms", 0, row, 3, row);
419
        basionymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
420
        basionymsComboboxSelect.withEditButton(true);
421
        basionymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
422
        basionymsComboboxSelect.setEditActionListener(e -> {
423

    
424
            Object fieldValue = e.getSource().getValue();
425
            UUID beanUuid = null;
426
            if(fieldValue != null){
427
                beanUuid = ((CdmBase)fieldValue).getUuid();
428

    
429
            }
430
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
431
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
432
        });
433
        grid.setComponentAlignment(basionymsComboboxSelect, Alignment.TOP_RIGHT);
434

    
435
        row++;
436
        basionymAuthorshipField = new TeamOrPersonField("Basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
437
        basionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
438
        addField(basionymAuthorshipField, "basionymAuthorship", 0, row, GRID_COLS-1, row);
439
        row++;
440
        exBasionymAuthorshipField = new TeamOrPersonField("Ex-basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
441
        exBasionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
442
        addField(exBasionymAuthorshipField, "exBasionymAuthorship", 0, row, GRID_COLS-1, row);
443

    
444
        // --------------- ReplacedSynonyms
445
        row++;
446
        replacedSynonymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Replaced synonym");
447
        replacedSynonymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
448
        addField(replacedSynonymsComboboxSelect, "replacedSynonyms", 0, row, 3, row);
449
        replacedSynonymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
450
        replacedSynonymsComboboxSelect.withEditButton(true);
451
        replacedSynonymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
452
        replacedSynonymsComboboxSelect.setEditActionListener(e -> {
453

    
454
            Object fieldValue = e.getSource().getValue();
455
            UUID beanUuid = null;
456
            if(fieldValue != null){
457
                beanUuid = ((CdmBase)fieldValue).getUuid();
458

    
459
            }
460
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
461
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
462
        });
463
        grid.setComponentAlignment(replacedSynonymsComboboxSelect, Alignment.TOP_RIGHT);
464

    
465
        // --------------- Validation
466
        row++;
467
        validationField = new NameRelationField("Validation of", "Designation", Direction.relatedTo, NameRelationshipType.VALIDATED_BY_NAME());
468
        validationField.setWidth(100, Unit.PERCENTAGE);
469
        ToOneRelatedEntityCombobox<TaxonName> validatedNameComboBox = validationField.getRelatedNameComboBox();
470
        validatedNameComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
471
                this,
472
                new TaxonNameEditorAction(EditorActionType.ADD, null, validatedNameComboBox, this)
473
                ));
474
        validatedNameComboBox.addClickListenerEditEntity(e -> {
475
            if(validatedNameComboBox.getValue() != null){
476
                getViewEventBus().publish(this,
477
                    new TaxonNameEditorAction(
478
                            EditorActionType.EDIT,
479
                            validatedNameComboBox.getValue().getUuid(),
480
                            e.getButton(),
481
                            validatedNameComboBox,
482
                            this)
483
                );
484
            }
485
        });
486
        ToOneRelatedEntityCombobox<Reference> validationCitatonComboBox = validationField.getCitatonComboBox();
487
        validationCitatonComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
488
                // NOTE: adding new references is currently not allowed for name relations, see NameRelationField!!
489
                this,
490
                new ReferenceEditorAction(EditorActionType.ADD, null, validationCitatonComboBox, this)
491
                ));
492
        validationCitatonComboBox.addClickListenerEditEntity(e -> {
493
            if(validationCitatonComboBox.getValue() != null){
494
                getViewEventBus().publish(this,
495
                    new ReferenceEditorAction(
496
                            EditorActionType.EDIT,
497
                            validationCitatonComboBox.getValue().getUuid(),
498
                            e.getButton(),
499
                            validationCitatonComboBox,
500
                            this)
501
                );
502
            }
503
        });
504
        addField(validationField, "validationFor", 0, row, 3, row);
505
        grid.setComponentAlignment(validationField, Alignment.TOP_RIGHT);
506

    
507
        // ------- Orthographic Variant (Correction)
508
        row++;
509
        orthographicVariantField = new NameRelationField("Orthographical variant", "Name variant", Direction.relatedTo, NameRelationshipType.ORTHOGRAPHIC_VARIANT());
510
        orthographicVariantField.setWidth(100, Unit.PERCENTAGE);
511
        // corrected name must have same
512
        ToOneRelatedEntityCombobox<TaxonName> orthographicVariantCombobox = orthographicVariantField.getRelatedNameComboBox();
513
        orthographicVariantCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
514
                this,
515
                new TaxonNameEditorAction(EditorActionType.ADD, null, orthographicVariantCombobox, this)
516
                ));
517
        orthographicVariantCombobox.addClickListenerEditEntity(e -> {
518
            if(orthographicVariantCombobox.getValue() != null){
519
                getViewEventBus().publish(this,
520
                    new TaxonNameEditorAction(
521
                            EditorActionType.EDIT,
522
                            orthographicVariantCombobox.getValue().getUuid(),
523
                            e.getButton(),
524
                            orthographicVariantCombobox,
525
                            this)
526
                );
527
            }
528
        });
529
        ToOneRelatedEntityCombobox<Reference> orthographicCorrectionCitatonComboBox = orthographicVariantField.getCitatonComboBox();
530
        orthographicCorrectionCitatonComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
531
                // NOTE: adding new references is currently not allowed for name relations, see NameRelationField!!
532
                this,
533
                new ReferenceEditorAction(EditorActionType.ADD, null, orthographicCorrectionCitatonComboBox, this)
534
                ));
535
        orthographicCorrectionCitatonComboBox.addClickListenerEditEntity(e -> {
536
            if(orthographicCorrectionCitatonComboBox.getValue() != null){
537
                getViewEventBus().publish(this,
538
                    new ReferenceEditorAction(
539
                            EditorActionType.EDIT,
540
                            orthographicCorrectionCitatonComboBox.getValue().getUuid(),
541
                            e.getButton(),
542
                            orthographicCorrectionCitatonComboBox,
543
                            this)
544
                );
545
            }
546
        });
547
        addField(orthographicVariantField, "orthographicVariant", 0, row, 3, row);
548
        grid.setComponentAlignment(orthographicVariantField, Alignment.TOP_RIGHT);
549

    
550
        row++;
551
        exCombinationAuthorshipField = new TeamOrPersonField("Ex-combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
552
        exCombinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
553
        addField(exCombinationAuthorshipField, "exCombinationAuthorship", 0, row, GRID_COLS-1, row);
554

    
555
        row++;
556
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
557
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
558
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProber(RolesAndPermissions.ROLE_CURATION));
559
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
560
        if(isCurator || isAdmin){
561
            annotationsListField.withNewButton(true);
562
        } else {
563
            annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
564
        }
565

    
566
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
567

    
568
        // -----------------------------------------------------------------------------
569

    
570
        setAdvancedModeEnabled(true);
571
        registerAdvancedModeComponents(fullTitleCacheFiled, protectedNameCacheField);
572

    
573
        registerAdvancedModeComponents(combinationAuthorshipField);
574
        registerAdvancedModeComponents(basionymAuthorshipField);
575
        registerAdvancedModeComponents(exBasionymAuthorshipField);
576
        registerAdvancedModeComponents(exCombinationAuthorshipField);
577

    
578
        registerAdvancedModeComponents(combinationAuthorshipField.getCachFields());
579
        registerAdvancedModeComponents(exCombinationAuthorshipField.getCachFields());
580
        registerAdvancedModeComponents(basionymAuthorshipField.getCachFields());
581
        registerAdvancedModeComponents(exBasionymAuthorshipField.getCachFields());
582

    
583
        setAdvancedMode(false);
584

    
585
        //TODO remove below line once #7858 is fixed
586
        withDeleteButton(false);
587

    
588
    }
589

    
590
    protected TeamOrPersonBase inferBasiomynAuthors() {
591
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
592
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
593
            TaxonName basionym = basionyms.get(0);
594
            if(basionym.getCombinationAuthorship() != null){
595
                return basionym.getCombinationAuthorship();
596
            } else if(basionym.getNomenclaturalReference() != null){
597
                return basionym.getNomenclaturalReference().getAuthorship();
598
            }
599
        }
600
        return null;
601
    }
602

    
603
    protected TeamOrPersonBase inferExBasiomynAuthors() {
604
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
605
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
606
            TaxonName basionym = basionyms.get(0);
607
                return basionym.getExCombinationAuthorship();
608
        }
609
        return null;
610
    }
611

    
612
    protected TeamOrPersonBase inferCombinationAuthors() {
613
        Reference nomRef = nomReferenceCombobox.getValue();
614
        if(nomRef != null) {
615
            return nomRef.getAuthorship();
616
        }
617
        return null;
618
    }
619

    
620
    protected TeamOrPersonBase inferExCombinationAuthors() {
621
        NameRelationshipDTO nameRelationDTO = validationField.getValue();
622

    
623
        TeamOrPersonBase inferredExAuthor = null;
624
        if(nameRelationDTO != null && nameRelationDTO.getOtherName() != null){
625
            TaxonName validatedName = nameRelationDTO.getOtherName();
626
            if(validatedName.getCombinationAuthorship() != null) {
627
                inferredExAuthor = validatedName.getCombinationAuthorship();
628
            } else if(validatedName.getNomenclaturalReference() != null){
629
                inferredExAuthor = validatedName.getNomenclaturalReference().getAuthorship();
630
            }
631
        }
632
        TeamOrPersonBase inferredCominationAuthors = inferCombinationAuthors();
633
        if(inferredExAuthor != null && inferredCominationAuthors != null
634
                // comparing by nomTitle to detect duplicates:
635
                && inferredExAuthor.getNomenclaturalTitle().equals(inferredCominationAuthors.getNomenclaturalTitle())) {
636
            // If and only if ex author = author the ex author is not included
637
            // into the author teams due to the ICN 46.10. (see #8317)
638
            inferredExAuthor = null;
639
        }
640
        return inferredExAuthor;
641
    }
642

    
643
    @Override
644
    protected void afterItemDataSourceSet() {
645

    
646

    
647
        rankSelect.addValueChangeListener(updateFieldVisibilityListener);
648
        basionymToggle.addValueChangeListener(e -> {
649
            updateAuthorshipFields();
650
        });
651
        validationToggle.addValueChangeListener(e -> {
652
            updateAuthorshipFields();
653
            });
654
        replacedSynonymsToggle.addValueChangeListener(e -> {
655
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
656
            replacedSynonymsComboboxSelect.setVisible(enable);
657
        });
658
        orthographicVariantToggle.addValueChangeListener(e -> {
659
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
660
            orthographicVariantField.setVisible(enable);
661
        });
662

    
663
        TaxonNameDTO taxonNameDTO = getBean();
664
        boolean showBasionymSection = taxonNameDTO.getBasionyms().size() > 0
665
                || taxonNameDTO.getBasionymAuthorship() != null
666
                || taxonNameDTO.getExBasionymAuthorship() != null;
667
        basionymToggle.setValue(showBasionymSection);
668
        basionymToggle.setReadOnly(showBasionymSection);
669

    
670
        boolean showReplacedSynonyms = taxonNameDTO.getReplacedSynonyms().size() > 0;
671
        replacedSynonymsToggle.setValue(showReplacedSynonyms);
672
        replacedSynonymsToggle.setReadOnly(showReplacedSynonyms);
673
        replacedSynonymsComboboxSelect.setVisible(showReplacedSynonyms);
674

    
675
        boolean showValidationSection = taxonNameDTO.getValidationFor() != null || taxonNameDTO.getExCombinationAuthorship() != null;
676
        validationToggle.setValue(showValidationSection);
677
        validationToggle.setReadOnly(showValidationSection);
678

    
679
        boolean showOrthographicCorrectionSection = taxonNameDTO.getOrthographicVariant() != null;
680
        orthographicVariantToggle.setValue(showOrthographicCorrectionSection);
681
        orthographicVariantToggle.setReadOnly(showOrthographicCorrectionSection);
682

    
683
        if(isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
684
            updateAuthorshipFields();
685
        }
686
        if(isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY) && getBean().getNomenclaturalReference() != null) {
687
            nomReferenceCombobox.setDescription("Selection limited to nomenclatural reference and parts of it.");
688
        }
689
        if(isModeEnabled(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE)) {
690
            nomReferenceCombobox.setRequired(true);
691
            nomReferenceCombobox.setImmediate(true);
692

    
693
            String userHint = "Please use the 'Edit' function to fix the problem in the related name.";
694
            validationField.getRelatedNameComboBox().getSelect().addValidator(new NomenclaturalReferenceExistsValidator(userHint));
695
            orthographicVariantField.getRelatedNameComboBox().getSelect().addValidator(new NomenclaturalReferenceExistsValidator(userHint));
696
            basionymsComboboxSelect.addFieldValidator(new NomenclaturalReferenceExistsValidator(userHint));
697
            replacedSynonymsComboboxSelect.addFieldValidator(new NomenclaturalReferenceExistsValidator(userHint));
698
        }
699
    }
700

    
701
    /**
702
     * Updates all authorship fields if the an authorship field is empty this method attempts to infer the
703
     * authors from the related nomenclatural reference or taxon name.
704
     * <p>
705
     * Finally the {@link #updateFieldVisibility()} is invoked.
706
     *
707
     * @param taxonName
708
     */
709
    @Override
710
    public void updateAuthorshipFields() {
711

    
712
        TaxonNameDTO taxonName = getBean();
713

    
714
        // ------------- CombinationAuthors
715
        isInferredCombinationAuthorship = updateAuthorshipFieldData(
716
                taxonName.getCombinationAuthorship(),
717
                inferCombinationAuthors(),
718
                combinationAuthorshipField,
719
                nomReferenceCombobox.getSelect(),
720
                isInferredCombinationAuthorship);
721

    
722

    
723
        // ------------- Basionym and ExBasionymAuthors
724
        if(BooleanUtils.isTrue(basionymToggle.getValue())){
725

    
726
            isInferredBasionymAuthorship = updateAuthorshipFieldData(
727
                    taxonName.getBasionymAuthorship(),
728
                    inferBasiomynAuthors(),
729
                    basionymAuthorshipField,
730
                    basionymsComboboxSelect,
731
                    isInferredBasionymAuthorship
732
                    );
733

    
734
            isInferredExBasionymAuthorship = updateAuthorshipFieldData(
735
                    taxonName.getExBasionymAuthorship(),
736
                    inferExBasiomynAuthors(),
737
                    exBasionymAuthorshipField,
738
                    basionymsComboboxSelect,
739
                    isInferredExBasionymAuthorship
740
                    );
741

    
742
        }
743

    
744
        // ------------- Validation and ExCombinationAuthors
745
        isInferredExCombinationAuthorship = updateAuthorshipFieldData(
746
                taxonName.getExCombinationAuthorship(),
747
                inferExCombinationAuthors(),
748
                exCombinationAuthorshipField,
749
                validationField.getRelatedNameComboBox(),
750
                isInferredExCombinationAuthorship
751
                );
752

    
753
        updateFieldVisibility();
754
    }
755

    
756

    
757
    /**
758
     *
759
     * @param authorship
760
     *    the value of the taxonName authorship field
761
     * @param inferredAuthors
762
     *    the value inferred from other fields which may be set as authorship to the taxon name
763
     * @param authorshipField
764
     *    the ui element to edit the taxonName authorship field
765
     * @param updateTriggerField
766
     * @param lastInferredAuthorshipState
767
     * @return
768
     */
769
    protected Boolean updateAuthorshipFieldData(TeamOrPersonBase<?> authorship, TeamOrPersonBase inferredAuthors,
770
            TeamOrPersonField authorshipField, AbstractField updateTriggerField,
771
            Boolean lastInferredAuthorshipState) {
772

    
773
        if(authorship == null){
774
            authorshipField.setValue(inferredAuthors);
775
            lastInferredAuthorshipState = true;
776
        } else {
777
            boolean authorshipMatch = authorship == inferredAuthors;
778
            if(lastInferredAuthorshipState == null){
779
                // initialization of authorshipState, this comes only into account when the editor is just being initialized
780
                lastInferredAuthorshipState = authorshipMatch;
781
            }
782
            if(!authorshipMatch && lastInferredAuthorshipState){
783
                // update the combinationAuthorshipField to follow changes of the nomenclatural reference in case it was autofilled before
784
                authorshipField.setValue(inferredAuthors);
785
                lastInferredAuthorshipState = true;
786
            }
787
        }
788

    
789
        if(updateTriggerField != null){
790
            // IMPORTANT!
791
            // this ChangeListener must be added at this very late point in the editor lifecycle so that it is called after
792
            // the ToOneRelatedEntityReloader which may have been added to the updateTriggerField in the presenters handleViewEntered() method.
793
            // Otherwise we risk multiple representation problems in the hibernate session
794
            if(!authorshipUpdateListeners.containsKey(updateTriggerField)){
795
                ValueChangeListener listener = e ->  {
796
                    logger.debug(" value changed #2");
797
                    updateAuthorshipFields();
798
                };
799
                updateTriggerField.addValueChangeListener(listener);
800
                authorshipUpdateListeners.put(updateTriggerField, listener);
801
            }
802
        }
803

    
804
        return lastInferredAuthorshipState;
805
    }
806

    
807
    /**
808
     * @param rank
809
     * @return
810
     */
811
    private void updateFieldVisibility() {
812

    
813
        // TODO use getField() instead and remove field references
814
        Rank rank = (Rank) rankSelect.getValue();
815

    
816
        boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES()) && !rank.getRankClass().equals(RankClass.Unknown);
817
        Boolean withBasionymSection = BooleanUtils.isTrue(basionymToggle.getValue());
818
        Boolean withValidationSection = BooleanUtils.isTrue(validationToggle.getValue());
819
        Boolean withOrthographicCorrectionSection = BooleanUtils.isTrue(orthographicVariantToggle.getValue());
820

    
821
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
822
            if(isSpeciesOrBelow) {
823
                if(TextField.class.isAssignableFrom(genusOrUninomialField.getClass())){
824
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
825
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
826
                            this,
827
                            new TaxonNameEditorActionStrRep(
828
                                    EditorActionType.ADD,
829
                                    e.getButton(),
830
                                    combobox,
831
                                    this)
832
                        ));
833
                    combobox.addClickListenerEditEntity(e -> {
834
                        //WeaklyRelatedEntityCombobox<TaxonName> wrcbbx = combobox;
835
                        if(combobox.getValue() != null){
836
                            getViewEventBus().publish(this,
837
                                new TaxonNameEditorActionStrRep(
838
                                        EditorActionType.EDIT,
839
                                        combobox.getIdForValue(),
840
                                        e.getButton(),
841
                                        combobox,
842
                                        this)
843
                            );
844
                        }
845
                    });
846
                    combobox.getSelect().setRequiredError(UIMessages.REQUIRED_SELECT_MISSING);
847
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, combobox, 0, genusOrUninomialRow, 1, genusOrUninomialRow);
848
                }
849
            } else {
850
                if(WeaklyRelatedEntityCombobox.class.isAssignableFrom(genusOrUninomialField.getClass())) {
851
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, new TextFieldNFix(), 0, genusOrUninomialRow, 1, genusOrUninomialRow);
852
                    genusOrUninomialField.setRequiredError(UIMessages.REQUIRED_TEXT_MISSING);
853
                }
854
            }
855
        }
856

    
857
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
858
            if(rank.isInfraSpecific()) {
859
                if(TextField.class.isAssignableFrom(specificEpithetField.getClass())) {
860
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
861
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, combobox, 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
862
                    combobox.getSelect().setRequiredError(UIMessages.REQUIRED_SELECT_MISSING);
863
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
864
                            this,
865
                            new TaxonNameEditorActionStrRep(EditorActionType.ADD, e.getButton(), combobox, this)
866
                        ));
867
                    combobox.addClickListenerEditEntity(e -> {
868
                        if(combobox.getValue() != null){
869
                            getViewEventBus().publish(this,
870
                                new TaxonNameEditorActionStrRep(
871
                                        EditorActionType.EDIT,
872
                                        combobox.getIdForValue(),
873
                                        e.getButton(),
874
                                        combobox,
875
                                        this)
876
                            );
877
                        }
878
                    });
879
                }
880
            } else {
881
                if(WeaklyRelatedEntityCombobox.class.isAssignableFrom(specificEpithetField.getClass())) {
882
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, new TextFieldNFix(), 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
883
                    specificEpithetField.setRequiredError(UIMessages.REQUIRED_TEXT_MISSING);
884
               }
885
            }
886
        }
887

    
888
        if(isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
889
            orthographicVariantField.setCaption("Orthographical correction");
890
            orthographicVariantField.getRelatedNameComboBox().setCaption("Incorrect name");
891
            orthographicVariantToggle.setCaption("Orthographical correction");
892
        } else {
893
            orthographicVariantField.setCaption("Orthographical variant");
894
            orthographicVariantField.getRelatedNameComboBox().setCaption("Name variant");
895
            orthographicVariantToggle.setCaption("Orthographical variant");
896
        }
897

    
898
        genusOrUninomialField.setRequired(true);
899
        specificEpithetField.setVisible(isSpeciesOrBelow);
900
        specificEpithetField.setRequired(isSpeciesOrBelow);
901
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
902
        infraSpecificEpithetField.setRequired(rank.isInfraSpecific());
903
        infraSpecificEpithetField.setRequiredError(UIMessages.REQUIRED_TEXT_MISSING);
904
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
905
        infraGenericEpithetField.setRequired(rank.isInfraGeneric());
906
        infraSpecificEpithetField.setRequiredError(UIMessages.REQUIRED_TEXT_MISSING);
907

    
908
        basionymsComboboxSelect.setVisible(withBasionymSection);
909

    
910
        combinationAuthorshipField.setVisible(isInferredCombinationAuthorship != null && !isInferredCombinationAuthorship);
911
        basionymAuthorshipField.setVisible(withBasionymSection && isInferredBasionymAuthorship != null && !isInferredBasionymAuthorship);
912
        exBasionymAuthorshipField.setVisible(withBasionymSection && isInferredExBasionymAuthorship != null && !isInferredExBasionymAuthorship);
913

    
914
        validationField.setVisible(withValidationSection);
915
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
916

    
917
        orthographicVariantField.setVisible(withOrthographicCorrectionSection);
918
        if(withOrthographicCorrectionSection){
919
            orthographicCorrectionValidator = new OrthographicCorrectionReferenceValidator(nomReferenceCombobox);
920
            orthographicVariantField.addValidator(orthographicCorrectionValidator);
921
        } else {
922
            if(orthographicCorrectionValidator  != null){
923
                orthographicVariantField.removeValidator(orthographicCorrectionValidator);
924
                orthographicVariantField = null;
925
            }
926
        }
927

    
928
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
929
        specificEpithetField.setVisible(isSpeciesOrBelow);
930
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
931
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
932

    
933
        updateNomStatusCollectionFieldVisibility();
934

    
935
    }
936

    
937
    public void updateNomStatusCollectionFieldVisibility() {
938
        boolean nameHasStatus = false;
939
        if(nomStatusCollectionField.getLayout().getRows() > 1) {
940
            // fist row holds the lables
941
            NativeSelect fistStatusSelect = (NativeSelect)nomStatusCollectionField.getLayout().getComponent(0, 1);
942
            nameHasStatus = fistStatusSelect.getValue() != null;
943
        }
944
        nomStatusCollectionField.getLayout().getParent().setVisible(nameHasStatus);
945
        nomStatusCollectionFieldToggle.setValue(Boolean.valueOf(nameHasStatus));
946
    }
947

    
948
    @Override
949
    public void cancel() {
950
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
951
        rankSelect.removeValueChangeListener(updateFieldVisibilityListener);
952
        super.cancel();
953
    }
954

    
955
    @Override
956
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
957
        return nomReferenceCombobox;
958
    }
959

    
960
    @Override
961
    public TextField getNomenclaturalReferenceDetail() {
962
        return nomenclaturalReferenceDetail;
963
    }
964

    
965
    @Override
966
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
967
        return basionymsComboboxSelect;
968
    }
969

    
970
    @Override
971
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
972
        return replacedSynonymsComboboxSelect;
973
    }
974

    
975
    @Override
976
    public NativeSelect getRankSelect() {
977
        return rankSelect;
978
    }
979

    
980
    @Override
981
    public AbstractField<String> getGenusOrUninomialField(){
982
        return genusOrUninomialField;
983
    }
984

    
985
    @Override
986
    public TeamOrPersonField getExBasionymAuthorshipField() {
987
        return exBasionymAuthorshipField;
988
    }
989

    
990
    @Override
991
    public TeamOrPersonField getBasionymAuthorshipField() {
992
        return basionymAuthorshipField;
993
    }
994

    
995
    @Override
996
    public TeamOrPersonField getCombinationAuthorshipField() {
997
        return combinationAuthorshipField;
998
    }
999

    
1000
    @Override
1001
    public TeamOrPersonField getExCombinationAuthorshipField() {
1002
        return exCombinationAuthorshipField;
1003
    }
1004

    
1005
    @Override
1006
    public NameRelationField getValidationField(){
1007
        return validationField;
1008
    }
1009

    
1010
    @Override
1011
    public NameRelationField getOrthographicVariantField() {
1012
        return orthographicVariantField;
1013
    }
1014

    
1015
    @Override
1016
    public void enableMode(TaxonNamePopupEditorMode mode){
1017
            modesActive.add(mode);
1018
            updateFormOnModeChange();
1019
    }
1020

    
1021
    @Override
1022
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
1023
        return modesActive.contains(mode);
1024
    }
1025

    
1026
    @Override
1027
    public void disableMode(TaxonNamePopupEditorMode mode){
1028
        modesActive.remove(mode);
1029
        updateFormOnModeChange();
1030
    }
1031

    
1032
    /**
1033
     * updates UI in turn of mode changes if needed, that is when the bean has been set
1034
     * already.
1035
     */
1036
    private void updateFormOnModeChange() {
1037
        if(getBean() != null){
1038
            // need to update the ui
1039
            afterItemDataSourceSet();
1040
            if(!isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
1041
                updateFieldVisibility();
1042
            }
1043
        }
1044
    }
1045

    
1046
    @Override
1047
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
1048
        return modesActive;
1049
    }
1050

    
1051
    @Override
1052
    public CheckBox getBasionymToggle() {
1053
        return basionymToggle;
1054
    }
1055

    
1056
    @Override
1057
    public FilterableAnnotationsField getAnnotationsField() {
1058
        return annotationsListField;
1059
    }
1060

    
1061
    @Override
1062
    public void setReadOnly(boolean readOnly) {
1063
        super.setReadOnly(readOnly);
1064
        boolean basionymToggleReadonly = basionymToggle.isReadOnly();
1065
        boolean validationToggleReadonly = validationToggle.isReadOnly();
1066
        combinationAuthorshipField.setEditorReadOnly(readOnly);
1067
        exCombinationAuthorshipField.setEditorReadOnly(readOnly);
1068
        basionymAuthorshipField.setEditorReadOnly(readOnly);
1069
        exBasionymAuthorshipField.setEditorReadOnly(readOnly);
1070
        // preserve old readonly states if they were true
1071
        if(basionymToggleReadonly){
1072
            basionymToggle.setReadOnly(true);
1073
        }
1074
        if(validationToggleReadonly){
1075
            validationToggle.setReadOnly(true);
1076
        }
1077
        nomStatusCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
1078
    }
1079

    
1080
    /**
1081
     * Sets the readonly state of all fields in this editor, but leaving the editor itself untouched.
1082
     *
1083
     * @param readOnly
1084
     */
1085
    public void setAllFieldsReadOnly(boolean readOnly) {
1086
        recursiveReadonly(readOnly, getMainLayout());
1087
        // NOTE:We are uUsing the enabled state instead of read only since
1088
        // setting read only will not affect the members editor.
1089
        // this seems to be a bug in TeamOrPersonField or in
1090
        // ToManyRelatedEntitiesListSelect
1091
        combinationAuthorshipField.setEnabled(!readOnly);
1092
        exCombinationAuthorshipField.setEnabled(!readOnly);
1093
        basionymAuthorshipField.setEnabled(!readOnly);
1094
        exBasionymAuthorshipField.setEnabled(!readOnly);
1095
        nomStatusCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
1096
    }
1097

    
1098
    @Override
1099
    public AbstractField<String> getInfraGenericEpithetField() {
1100
        return infraGenericEpithetField;
1101
    }
1102

    
1103
    @Override
1104
    public AbstractField<String> getSpecificEpithetField() {
1105
        return specificEpithetField;
1106
    }
1107

    
1108
    @Override
1109
    public AbstractField<String> getInfraSpecificEpithetField() {
1110
        return infraSpecificEpithetField;
1111
    }
1112

    
1113
    @Override
1114
    public CheckBox getOrthographicVariantToggle() {
1115
        return orthographicVariantToggle;
1116
    }
1117

    
1118
    @Override
1119
    public ElementCollectionField<NomenclaturalStatusDTO> getNomStatusCollectionField(){
1120
        return nomStatusCollectionField;
1121
    }
1122
}
(15-15/18)