Project

General

Profile

Download (48.1 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.NomenclaturalStatus;
45
import eu.etaxonomy.cdm.model.name.Rank;
46
import eu.etaxonomy.cdm.model.name.RankClass;
47
import eu.etaxonomy.cdm.model.name.TaxonName;
48
import eu.etaxonomy.cdm.model.reference.Reference;
49
import eu.etaxonomy.cdm.service.UserHelperAccess;
50
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
51
import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
52
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
53
import eu.etaxonomy.cdm.vaadin.data.validator.NomenclaturalReferenceExistsValidator;
54
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
55
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
56
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorActionStrRep;
57
import eu.etaxonomy.cdm.vaadin.model.name.NameRelationshipDTO;
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
 */
79
@SpringComponent
80
@Scope("prototype")
81
public class TaxonNamePopupEditor extends AbstractCdmDTOPopupEditor<TaxonNameDTO, TaxonName, TaxonNameEditorPresenter>
82
    implements TaxonNamePopupEditorView{
83

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

    
86
    private final static int GRID_COLS = 4;
87

    
88
    private final static int GRID_ROWS = 20;
89

    
90
    private static final boolean HAS_BASIONYM_DEFAULT = false;
91

    
92
    private AbstractField<String> genusOrUninomialField;
93

    
94
    private AbstractField<String> infraGenericEpithetField;
95

    
96
    private AbstractField<String> specificEpithetField;
97

    
98
    private AbstractField<String> infraSpecificEpithetField;
99

    
100
    private SwitchableTextField fullTitleCacheFiled;
101

    
102
    private SwitchableTextField protectedNameCacheField;
103

    
104
    private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
105

    
106
    private TextField nomenclaturalReferenceDetail;
107

    
108
    private TeamOrPersonField exBasionymAuthorshipField;
109

    
110
    private TeamOrPersonField basionymAuthorshipField;
111

    
112
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
113

    
114
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> replacedSynonymsComboboxSelect;
115

    
116
    private NameRelationField validationField;
117

    
118
    private NameRelationField orthographicVariantField;
119

    
120
    private ElementCollectionField<NomenclaturalStatus> nomStatusCollectionField;
121

    
122
    private CheckBox basionymToggle;
123

    
124
    private CheckBox replacedSynonymsToggle;
125

    
126
    private CheckBox validationToggle;
127

    
128
    private CheckBox orthographicVariantToggle;
129

    
130
    private NativeSelect rankSelect;
131

    
132
    private TeamOrPersonField combinationAuthorshipField;
133

    
134
    private TeamOrPersonField exCombinationAuthorshipField;
135

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

    
138
    private Boolean isInferredCombinationAuthorship = null;
139

    
140
    private Boolean isInferredBasionymAuthorship = null;
141

    
142
    private Boolean isInferredExBasionymAuthorship = null;
143

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

    
146
    private Boolean isInferredExCombinationAuthorship;
147

    
148
    private int specificEpithetFieldRow;
149

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

    
152
    private FilterableAnnotationsField annotationsListField;
153

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

    
156
    private int genusOrUninomialRow;
157

    
158
    private OrthographicCorrectionReferenceValidator orthographicCorrectionValidator;
159

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

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

    
181
    /**
182
     * @param layout
183
     * @param dtoType
184
     */
185
    public TaxonNamePopupEditor() {
186
        super(new GridLayout(GRID_COLS, GRID_ROWS), TaxonNameDTO.class);
187
    }
188

    
189
    /**
190
     * {@inheritDoc}
191
     */
192
    @Override
193
    public String getWindowCaption() {
194
        return "Name editor";
195
    }
196

    
197

    
198
    /**
199
     * {@inheritDoc}
200
     */
201
    @Override
202
    public int getWindowWidth() {
203
        return 800;
204
    }
205

    
206
    /**
207
     * {@inheritDoc}
208
     */
209
    @Override
210
    public void focusFirst() {
211
        // none
212
    }
213

    
214
    @Override
215
    public void applyDefaultComponentStyle(Component ... components){
216
        for(int i = 0; i <components.length; i++){
217
            components[i].setStyleName(getDefaultComponentStyles());
218
        }
219
    }
220

    
221
    /**
222
     * {@inheritDoc}
223
     */
224
    @Override
225
    protected String getDefaultComponentStyles() {
226
        return "tiny";
227
    }
228

    
229
    /**
230
     * {@inheritDoc}
231
     */
232
    @Override
233
    protected void initContent() {
234

    
235
        GridLayout grid = (GridLayout)getFieldLayout();
236
        grid.setSizeFull();
237
        grid.setHideEmptyRowsAndColumns(true);
238
        grid.setSpacing(true);
239
        grid.setColumnExpandRatio(0, 0.3f);
240
        grid.setColumnExpandRatio(1, 0.3f);
241
        grid.setColumnExpandRatio(2, 0.3f);
242
        grid.setColumnExpandRatio(3, 0.0f);
243

    
244
        /*
245
         - nameType: preset, needs to be set in the presenter for new names
246
         - appendedPhrase: -> TODO field
247
         - nomenclaturalMicroReference:  -> TODO field
248
         - nomenclaturalReference ->  field but disabled for REGISTRY
249
         - rank -> SelectField which determines the visiblity of the other fields
250

    
251
         - fullTitleCache + protectedFullTitleCache -> SwitchableTextField : ADVANCED_MODE
252
         - nameCache + protectedNameCache -> SwitchableTextField : ADVANCED_MODE
253

    
254
         - homotypicalGroup -> hidden
255
         - typeDesignations -> hidden
256
         - descriptions -> hidden
257
         - taxonBases -> hidden
258
         - registrations -> hidden
259

    
260
         - relationsFromThisName-> TODO implement later
261
         - relationsToThisName -> TODO implement later
262

    
263
         - genusOrUninomial -> textField
264
         - infraGenericEpithet  -> textField
265
         - specificEpithet  -> textField
266
         - infraSpecificEpithet  -> textField
267

    
268
         - authorshipCache + protectedAuthorshipCache -> SwitchableTextField : only ADVANCED_MODE and disabled for REGISTRY
269
         - basionymAuthorship -> field but disabled for REGISTRY, basionym is set as nameRelationShip
270
         - combinationAuthorship -> field but disabled for REGISTRY author team of the reference
271
         - exCombinationAuthorship -> textField
272
         - exBasionymAuthorship -> textField
273

    
274
         - status -> TODO field
275
         - monomHybrid -> TODO implement hybrids later
276
         - binomHybrid -> TODO implement hybrids later
277
         - trinomHybrid -> TODO implement hybrids later
278

    
279
         - hybridParentRelations -> TODO implement hybrids later
280
         - hybridChildRelations -> TODO implement hybrids later
281
         - hybridFormula -> TODO implement hybrids later
282

    
283
         ** ViralName attributes **
284
         - acronym
285

    
286
         ** BacterialName attributes **
287
         - subGenusAuthorship
288
         - nameApprobation
289
         - breed
290
         - publicationYear
291
         - originalPublicationYear
292
         - cultivarName
293
        */
294

    
295
        int row = 0;
296

    
297
        rankSelect = new NativeSelect("Rank");
298
        rankSelect.setNullSelectionAllowed(false);
299
        rankSelect.setWidth(100, Unit.PERCENTAGE);
300
        addField(rankSelect, "rank", 0, row, 1, row);
301
        grid.setComponentAlignment(rankSelect, Alignment.TOP_RIGHT);
302

    
303
        row++;
304
        basionymToggle = new CheckBox("With basionym");
305
        basionymToggle.setValue(HAS_BASIONYM_DEFAULT);
306
        basionymToggle.setStyleName(getDefaultComponentStyles());
307
        grid.addComponent(basionymToggle, 0, row);
308
        grid.setComponentAlignment(basionymToggle, Alignment.BOTTOM_LEFT);
309

    
310
        replacedSynonymsToggle = new CheckBox("With replaced synonym");
311
        grid.addComponent(replacedSynonymsToggle, 1, row);
312
        grid.setComponentAlignment(replacedSynonymsToggle, Alignment.BOTTOM_LEFT);
313

    
314
        validationToggle = new CheckBox("Validation");
315
        grid.addComponent(validationToggle, 2, row);
316
        grid.setComponentAlignment(validationToggle, Alignment.BOTTOM_LEFT);
317

    
318
        orthographicVariantToggle = new CheckBox("Orthographical variant");
319
        grid.addComponent(orthographicVariantToggle, 3, row);
320
        grid.setComponentAlignment(orthographicVariantToggle, Alignment.BOTTOM_LEFT);
321

    
322
        row++;
323
        // fullTitleCache
324
        fullTitleCacheFiled = addSwitchableTextField("Full title cache", "fullTitleCache", "protectedFullTitleCache", 0, row, GRID_COLS-1, row);
325
        fullTitleCacheFiled.setWidth(100, Unit.PERCENTAGE);
326
        row++;
327
        protectedNameCacheField = addSwitchableTextField("Name cache", "nameCache", "protectedNameCache", 0, row, GRID_COLS-1, row);
328
        protectedNameCacheField.setWidth(100, Unit.PERCENTAGE);
329
        row++;
330
        genusOrUninomialRow = row;
331
        genusOrUninomialField = addTextField("Genus or uninomial", "genusOrUninomial", 0, row, 1, row);
332
        genusOrUninomialField.setWidth(200, Unit.PIXELS);
333
        infraGenericEpithetField = addTextField("Infrageneric epithet", "infraGenericEpithet", 2, row, 3, row);
334
        infraGenericEpithetField.setWidth(200, Unit.PIXELS);
335
        row++;
336
        specificEpithetFieldRow = row;
337
        specificEpithetField = addTextField("Specific epithet", "specificEpithet", 0, row, 1, row);
338
        specificEpithetField.setWidth(200, Unit.PIXELS);
339
        infraSpecificEpithetField = addTextField("Infraspecific epithet", "infraSpecificEpithet", 2, row, 3, row);
340
        infraSpecificEpithetField.setWidth(200, Unit.PIXELS);
341

    
342
        row++;
343
        combinationAuthorshipField = new TeamOrPersonField("Combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
344
        combinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
345
        addField(combinationAuthorshipField, "combinationAuthorship", 0, row, GRID_COLS-1, row);
346

    
347
        row++;
348
        nomReferenceCombobox = new ToOneRelatedEntityCombobox<Reference>("Nomenclatural reference", Reference.class);
349
        nomReferenceCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
350
                this,
351
                new ReferenceEditorAction(EditorActionType.ADD, null, nomReferenceCombobox, this)
352
                ));
353
        nomReferenceCombobox.addClickListenerEditEntity(e -> {
354
            if(nomReferenceCombobox.getValue() != null){
355
                getViewEventBus().publish(this,
356
                    new ReferenceEditorAction(
357
                            EditorActionType.EDIT,
358
                            nomReferenceCombobox.getValue().getUuid(),
359
                            e.getButton(),
360
                            nomReferenceCombobox,
361
                            this)
362
                );
363
            }
364
            });
365

    
366

    
367
        // nomReferenceCombobox.getSelect().addValueChangeListener(e -> logger.debug("nomReferenceCombobox value changed #1"));
368
        // nomReferenceCombobox.setWidth(300, Unit.PIXELS);
369
        nomReferenceCombobox.setWidth("100%");
370
        addField(nomReferenceCombobox, "nomenclaturalReference", 0, row, 3, row);
371

    
372
        row++;
373
        nomenclaturalReferenceDetail = addTextField("Reference detail", "nomenclaturalMicroReference", 0, row, 2, row);
374
        nomenclaturalReferenceDetail.setWidth(100, Unit.PERCENTAGE);
375

    
376
        // --------------- nom status
377
        row++;
378
        nomStatusCollectionField = new ElementCollectionField<NomenclaturalStatus>(
379
                NomenclaturalStatus.class,
380
                new Instantiator<NomenclaturalStatus>() {
381

    
382
                    @Override
383
                    public NomenclaturalStatus create() {
384
                        return NomenclaturalStatus.NewInstance(null);
385
                    }
386
                },
387
                NomenclaturalStatusRow.class
388
                ){
389

    
390
                    @Override
391
                    public void commit() throws SourceException, InvalidValueException {
392
                        validate(); // validate always so that empty rows are recognized
393
                        super.commit();
394
                    }
395

    
396
                    @Override
397
                    public boolean isEmpty() {
398
                        Collection value = getValue();
399
                        return value == null || value.isEmpty() ;
400
                    }
401

    
402
                    @Override
403
                    public void setComponentError(ErrorMessage componentError) {
404
                        nomStatusCollectionField.setComponentError(componentError);
405
                    }
406

    
407
        };
408

    
409
        nomStatusCollectionField.getLayout().setSpacing(false);
410
        nomStatusCollectionField.setVisibleProperties(NomenclaturalStatusRow.visibleFields());
411
        nomStatusCollectionField.setPropertyHeader("type", "Status type");
412
        nomStatusCollectionField.setPropertyHeader("citation", "Reference");
413
        nomStatusCollectionField.setPropertyHeader("citationMicroReference", "Reference detail");
414
        nomStatusCollectionField.setPropertyHeader("ruleConsidered", "Rule considered");
415
        nomStatusCollectionField.addElementAddedListener( e -> nomStatusCollectionField.setComponentError(null));
416
        nomStatusCollectionField.getLayout().setMargin(new MarginInfo(false, true));
417

    
418
        Panel nomStatusCollectionPanel = new Panel(nomStatusCollectionField.getLayout());
419
        nomStatusCollectionPanel.setCaption("Status");
420
        nomStatusCollectionPanel.setWidth(100, Unit.PERCENTAGE);
421

    
422
        bindField(nomStatusCollectionField, "status");
423
        addComponent(nomStatusCollectionPanel, 0, row, 3, row);
424

    
425
        // --------------- Basionyms
426
        row++;
427
        basionymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Basionym");
428
        basionymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
429
        addField(basionymsComboboxSelect, "basionyms", 0, row, 3, row);
430
        basionymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
431
        basionymsComboboxSelect.withEditButton(true);
432
        basionymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
433
        basionymsComboboxSelect.setEditActionListener(e -> {
434

    
435
            Object fieldValue = e.getSource().getValue();
436
            UUID beanUuid = null;
437
            if(fieldValue != null){
438
                beanUuid = ((CdmBase)fieldValue).getUuid();
439

    
440
            }
441
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
442
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
443
        });
444
        grid.setComponentAlignment(basionymsComboboxSelect, Alignment.TOP_RIGHT);
445

    
446
        row++;
447
        basionymAuthorshipField = new TeamOrPersonField("Basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
448
        basionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
449
        addField(basionymAuthorshipField, "basionymAuthorship", 0, row, GRID_COLS-1, row);
450
        row++;
451
        exBasionymAuthorshipField = new TeamOrPersonField("Ex-basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
452
        exBasionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
453
        addField(exBasionymAuthorshipField, "exBasionymAuthorship", 0, row, GRID_COLS-1, row);
454

    
455
        // --------------- ReplacedSynonyms
456
        row++;
457
        replacedSynonymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Replaced synonym");
458
        replacedSynonymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
459
        addField(replacedSynonymsComboboxSelect, "replacedSynonyms", 0, row, 3, row);
460
        replacedSynonymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
461
        replacedSynonymsComboboxSelect.withEditButton(true);
462
        replacedSynonymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
463
        replacedSynonymsComboboxSelect.setEditActionListener(e -> {
464

    
465
            Object fieldValue = e.getSource().getValue();
466
            UUID beanUuid = null;
467
            if(fieldValue != null){
468
                beanUuid = ((CdmBase)fieldValue).getUuid();
469

    
470
            }
471
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
472
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
473
        });
474
        grid.setComponentAlignment(replacedSynonymsComboboxSelect, Alignment.TOP_RIGHT);
475

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

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

    
561
        row++;
562
        exCombinationAuthorshipField = new TeamOrPersonField("Ex-combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
563
        exCombinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
564
        addField(exCombinationAuthorshipField, "exCombinationAuthorship", 0, row, GRID_COLS-1, row);
565

    
566
        row++;
567
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
568
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
569
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProber(RolesAndPermissions.ROLE_CURATION));
570
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
571
        if(isCurator || isAdmin){
572
            annotationsListField.withNewButton(true);
573
        } else {
574
            annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
575
        }
576

    
577
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
578

    
579
        // -----------------------------------------------------------------------------
580

    
581
        setAdvancedModeEnabled(true);
582
        registerAdvancedModeComponents(fullTitleCacheFiled, protectedNameCacheField);
583

    
584
        registerAdvancedModeComponents(combinationAuthorshipField);
585
        registerAdvancedModeComponents(basionymAuthorshipField);
586
        registerAdvancedModeComponents(exBasionymAuthorshipField);
587
        registerAdvancedModeComponents(exCombinationAuthorshipField);
588

    
589
        registerAdvancedModeComponents(combinationAuthorshipField.getCachFields());
590
        registerAdvancedModeComponents(exCombinationAuthorshipField.getCachFields());
591
        registerAdvancedModeComponents(basionymAuthorshipField.getCachFields());
592
        registerAdvancedModeComponents(exBasionymAuthorshipField.getCachFields());
593

    
594
        setAdvancedMode(false);
595

    
596
        //TODO remove below line once #7858 is fixed
597
        withDeleteButton(false);
598

    
599
    }
600

    
601
    protected TeamOrPersonBase inferBasiomynAuthors() {
602
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
603
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
604
            TaxonName basionym = basionyms.get(0);
605
            if(basionym.getCombinationAuthorship() != null){
606
                return basionym.getCombinationAuthorship();
607
            } else if(basionym.getNomenclaturalReference() != null){
608
                return basionym.getNomenclaturalReference().getAuthorship();
609
            }
610
        }
611
        return null;
612
    }
613

    
614
    protected TeamOrPersonBase inferExBasiomynAuthors() {
615
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
616
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
617
            TaxonName basionym = basionyms.get(0);
618
                return basionym.getExCombinationAuthorship();
619
        }
620
        return null;
621
    }
622

    
623
    protected TeamOrPersonBase inferCombinationAuthors() {
624
        Reference nomRef = nomReferenceCombobox.getValue();
625
        if(nomRef != null) {
626
            return nomRef.getAuthorship();
627
        }
628
        return null;
629
    }
630

    
631
    protected TeamOrPersonBase inferExCombinationAuthors() {
632
        NameRelationshipDTO nameRelationDTO = validationField.getValue();
633

    
634
        TeamOrPersonBase inferredExAuthor = null;
635
        if(nameRelationDTO != null && nameRelationDTO.getOtherName() != null){
636
            TaxonName validatedName = nameRelationDTO.getOtherName();
637
            if(validatedName.getCombinationAuthorship() != null) {
638
                inferredExAuthor = validatedName.getCombinationAuthorship();
639
            } else if(validatedName.getNomenclaturalReference() != null){
640
                inferredExAuthor = validatedName.getNomenclaturalReference().getAuthorship();
641
            }
642
        }
643
        if(inferredExAuthor != null && inferredExAuthor.equals(inferCombinationAuthors())) {
644
            // If and only if ex author = author the ex author is not included
645
            // into the author teams due to the ICN 46.10. (see #8317)
646
            inferredExAuthor = null;
647
        }
648
        return inferredExAuthor;
649
    }
650

    
651
    @Override
652
    protected void afterItemDataSourceSet() {
653

    
654

    
655
        rankSelect.addValueChangeListener(updateFieldVisibilityListener);
656
        basionymToggle.addValueChangeListener(e -> {
657
            updateAuthorshipFields();
658
        });
659
        validationToggle.addValueChangeListener(e -> {
660
            updateAuthorshipFields();
661
            });
662
        replacedSynonymsToggle.addValueChangeListener(e -> {
663
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
664
            replacedSynonymsComboboxSelect.setVisible(enable);
665
        });
666
        orthographicVariantToggle.addValueChangeListener(e -> {
667
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
668
            orthographicVariantField.setVisible(enable);
669
        });
670

    
671
        TaxonNameDTO taxonNameDTO = getBean();
672
        boolean showBasionymSection = taxonNameDTO.getBasionyms().size() > 0
673
                || taxonNameDTO.getBasionymAuthorship() != null
674
                || taxonNameDTO.getExBasionymAuthorship() != null;
675
        basionymToggle.setValue(showBasionymSection);
676
        basionymToggle.setReadOnly(showBasionymSection);
677

    
678
        boolean showReplacedSynonyms = taxonNameDTO.getReplacedSynonyms().size() > 0;
679
        replacedSynonymsToggle.setValue(showReplacedSynonyms);
680
        replacedSynonymsToggle.setReadOnly(showReplacedSynonyms);
681
        replacedSynonymsComboboxSelect.setVisible(showReplacedSynonyms);
682

    
683
        boolean showValidationSection = taxonNameDTO.getValidationFor() != null || taxonNameDTO.getExCombinationAuthorship() != null;
684
        validationToggle.setValue(showValidationSection);
685
        validationToggle.setReadOnly(showValidationSection);
686

    
687
        boolean showOrthographicCorrectionSection = taxonNameDTO.getOrthographicVariant() != null;
688
        orthographicVariantToggle.setValue(showOrthographicCorrectionSection);
689
        orthographicVariantToggle.setReadOnly(showOrthographicCorrectionSection);
690

    
691
        if(isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
692
            updateAuthorshipFields();
693
        }
694
        if(isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY) && getBean().getNomenclaturalReference() != null) {
695
            nomReferenceCombobox.setDescription("Selection limited to nomenclatural reference and parts of it.");
696
        }
697
        if(isModeEnabled(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE)) {
698
            nomReferenceCombobox.setRequired(true);
699
            nomReferenceCombobox.setImmediate(true);
700

    
701
            String userHint = "Please use the 'Edit' function to fix the problem in the related name.";
702
            validationField.getRelatedNameComboBox().getSelect().addValidator(new NomenclaturalReferenceExistsValidator(userHint));
703
            orthographicVariantField.getRelatedNameComboBox().getSelect().addValidator(new NomenclaturalReferenceExistsValidator(userHint));
704
            basionymsComboboxSelect.addFieldValidator(new NomenclaturalReferenceExistsValidator(userHint));
705
            replacedSynonymsComboboxSelect.addFieldValidator(new NomenclaturalReferenceExistsValidator(userHint));
706
        }
707
    }
708

    
709
    /**
710
     * Updates all authorship fields if the an authorship field is empty this method attempts to infer the
711
     * authors from the related nomenclatural reference or taxon name.
712
     * <p>
713
     * Finally the {@link #updateFieldVisibility()} is invoked.
714
     *
715
     * @param taxonName
716
     */
717
    @Override
718
    public void updateAuthorshipFields() {
719

    
720
        TaxonNameDTO taxonName = getBean();
721

    
722
        // ------------- CombinationAuthors
723
        isInferredCombinationAuthorship = updateAuthorshipFieldData(
724
                taxonName.getCombinationAuthorship(),
725
                inferCombinationAuthors(),
726
                combinationAuthorshipField,
727
                nomReferenceCombobox.getSelect(),
728
                isInferredCombinationAuthorship);
729

    
730

    
731
        // ------------- Basionym and ExBasionymAuthors
732
        if(BooleanUtils.isTrue(basionymToggle.getValue())){
733

    
734
            isInferredBasionymAuthorship = updateAuthorshipFieldData(
735
                    taxonName.getBasionymAuthorship(),
736
                    inferBasiomynAuthors(),
737
                    basionymAuthorshipField,
738
                    basionymsComboboxSelect,
739
                    isInferredBasionymAuthorship
740
                    );
741

    
742
            isInferredExBasionymAuthorship = updateAuthorshipFieldData(
743
                    taxonName.getExBasionymAuthorship(),
744
                    inferExBasiomynAuthors(),
745
                    exBasionymAuthorshipField,
746
                    basionymsComboboxSelect,
747
                    isInferredExBasionymAuthorship
748
                    );
749

    
750
        }
751

    
752
        // ------------- Validation and ExCombinationAuthors
753
        isInferredExCombinationAuthorship = updateAuthorshipFieldData(
754
                taxonName.getExCombinationAuthorship(),
755
                inferExCombinationAuthors(),
756
                exCombinationAuthorshipField,
757
                validationField.getRelatedNameComboBox(),
758
                isInferredExCombinationAuthorship
759
                );
760

    
761
        updateFieldVisibility();
762
    }
763

    
764

    
765
    /**
766
     *
767
     * @param authorship
768
     *    the value of the taxonName authorship field
769
     * @param inferredAuthors
770
     *    the value inferred from other fields which may be set as authorship to the taxon name
771
     * @param authorshipField
772
     *    the ui element to edit the taxonName authorship field
773
     * @param updateTriggerField
774
     * @param lastInferredAuthorshipState
775
     * @return
776
     */
777
    protected Boolean updateAuthorshipFieldData(TeamOrPersonBase<?> authorship, TeamOrPersonBase inferredAuthors,
778
            TeamOrPersonField authorshipField, AbstractField updateTriggerField,
779
            Boolean lastInferredAuthorshipState) {
780

    
781
        if(authorship == null){
782
            authorshipField.setValue(inferredAuthors);
783
            lastInferredAuthorshipState = true;
784
        } else {
785
            boolean authorshipMatch = authorship == inferredAuthors;
786
            if(lastInferredAuthorshipState == null){
787
                // initialization of authorshipState, this comes only into account when the editor is just being initialized
788
                lastInferredAuthorshipState = authorshipMatch;
789
            }
790
            if(!authorshipMatch && lastInferredAuthorshipState){
791
                // update the combinationAuthorshipField to follow changes of the nomenclatural reference in case it was autofilled before
792
                authorshipField.setValue(inferredAuthors);
793
                lastInferredAuthorshipState = true;
794
            }
795
        }
796

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

    
812
        return lastInferredAuthorshipState;
813
    }
814

    
815
    /**
816
     * @param rank
817
     * @return
818
     */
819
    private void updateFieldVisibility() {
820

    
821
        // TODO use getField() instead and remove field references
822
        Rank rank = (Rank) rankSelect.getValue();
823

    
824
        boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES()) && !rank.getRankClass().equals(RankClass.Unknown);
825
        Boolean withBasionymSection = BooleanUtils.isTrue(basionymToggle.getValue());
826
        Boolean withValidationSection = BooleanUtils.isTrue(validationToggle.getValue());
827
        Boolean withOrthographicCorrectionSection = BooleanUtils.isTrue(orthographicVariantToggle.getValue());
828

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

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

    
896
        if(isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
897
            orthographicVariantField.setCaption("Orthographical correction");
898
            orthographicVariantField.getRelatedNameComboBox().setCaption("Incorrect name");
899
            orthographicVariantToggle.setCaption("Orthographical correction");
900
        } else {
901
            orthographicVariantField.setCaption("Orthographical variant");
902
            orthographicVariantField.getRelatedNameComboBox().setCaption("Name variant");
903
            orthographicVariantToggle.setCaption("Orthographical variant");
904
        }
905

    
906
        genusOrUninomialField.setRequired(true);
907
        specificEpithetField.setVisible(isSpeciesOrBelow);
908
        specificEpithetField.setRequired(isSpeciesOrBelow);
909
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
910
        infraSpecificEpithetField.setRequired(rank.isInfraSpecific());
911
        infraSpecificEpithetField.setRequiredError(UIMessages.REQUIRED_TEXT_MISSING);
912
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
913
        infraGenericEpithetField.setRequired(rank.isInfraGeneric());
914
        infraSpecificEpithetField.setRequiredError(UIMessages.REQUIRED_TEXT_MISSING);
915

    
916
        basionymsComboboxSelect.setVisible(withBasionymSection);
917

    
918
        combinationAuthorshipField.setVisible(isInferredCombinationAuthorship != null && !isInferredCombinationAuthorship);
919
        basionymAuthorshipField.setVisible(withBasionymSection && isInferredBasionymAuthorship != null && !isInferredBasionymAuthorship);
920
        exBasionymAuthorshipField.setVisible(withBasionymSection && isInferredExBasionymAuthorship != null && !isInferredExBasionymAuthorship);
921

    
922
        validationField.setVisible(withValidationSection);
923
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
924

    
925
        orthographicVariantField.setVisible(withOrthographicCorrectionSection);
926
        if(withOrthographicCorrectionSection){
927
            orthographicCorrectionValidator = new OrthographicCorrectionReferenceValidator(nomReferenceCombobox);
928
            orthographicVariantField.addValidator(orthographicCorrectionValidator);
929
        } else {
930
            if(orthographicCorrectionValidator  != null){
931
                orthographicVariantField.removeValidator(orthographicCorrectionValidator);
932
                orthographicVariantField = null;
933
            }
934
        }
935

    
936
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
937
        specificEpithetField.setVisible(isSpeciesOrBelow);
938
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
939
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
940
    }
941

    
942

    
943
    @Override
944
    public void cancel() {
945
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
946
        rankSelect.removeValueChangeListener(updateFieldVisibilityListener);
947
        super.cancel();
948
    }
949

    
950

    
951
    /**
952
     * {@inheritDoc}
953
     */
954
    @Override
955
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
956
        return nomReferenceCombobox;
957
    }
958

    
959

    
960
    /**
961
     * {@inheritDoc}
962
     */
963
    @Override
964
    public TextField getNomenclaturalReferenceDetail() {
965
        return nomenclaturalReferenceDetail;
966
    }
967

    
968
    /**
969
     * {@inheritDoc}
970
     */
971
    @Override
972
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
973
        return basionymsComboboxSelect;
974
    }
975

    
976
    /**
977
     * {@inheritDoc}
978
     */
979
    @Override
980
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
981
        return replacedSynonymsComboboxSelect;
982
    }
983

    
984
    /**
985
     * {@inheritDoc}
986
     */
987
    @Override
988
    public NativeSelect getRankSelect() {
989
        return rankSelect;
990
    }
991

    
992
    /**
993
     * {@inheritDoc}
994
     */
995
    @Override
996
    public AbstractField<String> getGenusOrUninomialField(){
997
        return genusOrUninomialField;
998
    }
999

    
1000
    /**
1001
     * @return the exBasionymAuthorshipField
1002
     */
1003
    @Override
1004
    public TeamOrPersonField getExBasionymAuthorshipField() {
1005
        return exBasionymAuthorshipField;
1006
    }
1007

    
1008
    /**
1009
     * @return the basionymAuthorshipField
1010
     */
1011
    @Override
1012
    public TeamOrPersonField getBasionymAuthorshipField() {
1013
        return basionymAuthorshipField;
1014
    }
1015

    
1016
    /**
1017
     * @return the combinationAuthorshipField
1018
     */
1019
    @Override
1020
    public TeamOrPersonField getCombinationAuthorshipField() {
1021
        return combinationAuthorshipField;
1022
    }
1023

    
1024
    /**
1025
     * @return the exCombinationAuthorshipField
1026
     */
1027
    @Override
1028
    public TeamOrPersonField getExCombinationAuthorshipField() {
1029
        return exCombinationAuthorshipField;
1030
    }
1031

    
1032
    @Override
1033
    public NameRelationField getValidationField(){
1034
        return validationField;
1035
    }
1036

    
1037
    @Override
1038
    public NameRelationField getOrthographicVariantField() {
1039
        return orthographicVariantField;
1040
    }
1041

    
1042
    @Override
1043
    public void enableMode(TaxonNamePopupEditorMode mode){
1044
            modesActive.add(mode);
1045
            updateFormOnModeChange();
1046
    }
1047

    
1048
    @Override
1049
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
1050
        return modesActive.contains(mode);
1051
    }
1052

    
1053
    @Override
1054
    public void disableMode(TaxonNamePopupEditorMode mode){
1055
        modesActive.remove(mode);
1056
        updateFormOnModeChange();
1057
    }
1058

    
1059
    /**
1060
     * updates UI in turn of mode changes if needed, that is when the bean has been set
1061
     * already.
1062
     */
1063
    private void updateFormOnModeChange() {
1064
        if(getBean() != null){
1065
            // need to update the ui
1066
            afterItemDataSourceSet();
1067
            if(!isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
1068
                updateFieldVisibility();
1069
            }
1070
        }
1071
    }
1072

    
1073
    @Override
1074
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
1075
        return modesActive;
1076
    }
1077

    
1078
    @Override
1079
    public CheckBox getBasionymToggle() {
1080
        return basionymToggle;
1081
    }
1082

    
1083
    @Override
1084
    public FilterableAnnotationsField getAnnotationsField() {
1085
        return annotationsListField;
1086
    }
1087

    
1088
    /**
1089
     * {@inheritDoc}
1090
     */
1091
    @Override
1092
    public void setReadOnly(boolean readOnly) {
1093
        super.setReadOnly(readOnly);
1094
        boolean basionymToggleReadonly = basionymToggle.isReadOnly();
1095
        boolean validationToggleReadonly = validationToggle.isReadOnly();
1096
        combinationAuthorshipField.setEditorReadOnly(readOnly);
1097
        exCombinationAuthorshipField.setEditorReadOnly(readOnly);
1098
        basionymAuthorshipField.setEditorReadOnly(readOnly);
1099
        exBasionymAuthorshipField.setEditorReadOnly(readOnly);
1100
        // preserve old readonly states if they were true
1101
        if(basionymToggleReadonly){
1102
            basionymToggle.setReadOnly(true);
1103
        }
1104
        if(validationToggleReadonly){
1105
            validationToggle.setReadOnly(true);
1106
        }
1107
        nomStatusCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
1108
    }
1109

    
1110
    /**
1111
     * Sets the readonly state of all fields in this editor, but leaving the editor itself untouched.
1112
     *
1113
     * @param readOnly
1114
     */
1115
    public void setAllFieldsReadOnly(boolean readOnly) {
1116
        recursiveReadonly(readOnly, getMainLayout());
1117
        // NOTE:We are uUsing the enabled state instead of read only since
1118
        // setting read only will not affect the members editor.
1119
        // this seems to be a bug in TeamOrPersonField or in
1120
        // ToManyRelatedEntitiesListSelect
1121
        combinationAuthorshipField.setEnabled(!readOnly);
1122
        exCombinationAuthorshipField.setEnabled(!readOnly);
1123
        basionymAuthorshipField.setEnabled(!readOnly);
1124
        exBasionymAuthorshipField.setEnabled(!readOnly);
1125
        nomStatusCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
1126
    }
1127

    
1128

    
1129
    /**
1130
     * @return the infraGenericEpithetField
1131
     */
1132
    @Override
1133
    public AbstractField<String> getInfraGenericEpithetField() {
1134
        return infraGenericEpithetField;
1135
    }
1136

    
1137
    /**
1138
     * @return the specificEpithetField
1139
     */
1140
    @Override
1141
    public AbstractField<String> getSpecificEpithetField() {
1142
        return specificEpithetField;
1143
    }
1144

    
1145
    /**
1146
     * @return the infraSpecificEpithetField
1147
     */
1148
    @Override
1149
    public AbstractField<String> getInfraSpecificEpithetField() {
1150
        return infraSpecificEpithetField;
1151
    }
1152

    
1153
    @Override
1154
    public CheckBox getOrthographicVariantToggle() {
1155
        return orthographicVariantToggle;
1156
    }
1157

    
1158
    @Override
1159
    public ElementCollectionField<NomenclaturalStatus> getNomStatusCollectionField(){
1160
        return nomStatusCollectionField;
1161
    }
1162

    
1163
}
(12-12/15)