Project

General

Profile

Download (47.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.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
        if(nameRelationDTO != null && nameRelationDTO.getOtherName() != null){
634
            TaxonName validatedName = nameRelationDTO.getOtherName();
635
            if(validatedName.getCombinationAuthorship() != null) {
636
                return validatedName.getCombinationAuthorship();
637
            } else if(validatedName.getNomenclaturalReference() != null){
638
                return validatedName.getNomenclaturalReference().getAuthorship();
639
            }
640
        }
641
        return null;
642
    }
643

    
644
    @Override
645
    protected void afterItemDataSourceSet() {
646

    
647

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

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

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

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

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

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

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

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

    
713
        TaxonNameDTO taxonName = getBean();
714

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

    
723

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

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

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

    
743
        }
744

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

    
754
        updateFieldVisibility();
755
    }
756

    
757

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

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

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

    
805
        return lastInferredAuthorshipState;
806
    }
807

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

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

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

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

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

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

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

    
909
        basionymsComboboxSelect.setVisible(withBasionymSection);
910

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

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

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

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

    
935

    
936
    @Override
937
    public void cancel() {
938
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
939
        rankSelect.removeValueChangeListener(updateFieldVisibilityListener);
940
        super.cancel();
941
    }
942

    
943

    
944
    /**
945
     * {@inheritDoc}
946
     */
947
    @Override
948
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
949
        return nomReferenceCombobox;
950
    }
951

    
952

    
953
    /**
954
     * {@inheritDoc}
955
     */
956
    @Override
957
    public TextField getNomenclaturalReferenceDetail() {
958
        return nomenclaturalReferenceDetail;
959
    }
960

    
961
    /**
962
     * {@inheritDoc}
963
     */
964
    @Override
965
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
966
        return basionymsComboboxSelect;
967
    }
968

    
969
    /**
970
     * {@inheritDoc}
971
     */
972
    @Override
973
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
974
        return replacedSynonymsComboboxSelect;
975
    }
976

    
977
    /**
978
     * {@inheritDoc}
979
     */
980
    @Override
981
    public NativeSelect getRankSelect() {
982
        return rankSelect;
983
    }
984

    
985
    /**
986
     * {@inheritDoc}
987
     */
988
    @Override
989
    public AbstractField<String> getGenusOrUninomialField(){
990
        return genusOrUninomialField;
991
    }
992

    
993
    /**
994
     * @return the exBasionymAuthorshipField
995
     */
996
    @Override
997
    public TeamOrPersonField getExBasionymAuthorshipField() {
998
        return exBasionymAuthorshipField;
999
    }
1000

    
1001
    /**
1002
     * @return the basionymAuthorshipField
1003
     */
1004
    @Override
1005
    public TeamOrPersonField getBasionymAuthorshipField() {
1006
        return basionymAuthorshipField;
1007
    }
1008

    
1009
    /**
1010
     * @return the combinationAuthorshipField
1011
     */
1012
    @Override
1013
    public TeamOrPersonField getCombinationAuthorshipField() {
1014
        return combinationAuthorshipField;
1015
    }
1016

    
1017
    /**
1018
     * @return the exCombinationAuthorshipField
1019
     */
1020
    @Override
1021
    public TeamOrPersonField getExCombinationAuthorshipField() {
1022
        return exCombinationAuthorshipField;
1023
    }
1024

    
1025
    @Override
1026
    public NameRelationField getValidationField(){
1027
        return validationField;
1028
    }
1029

    
1030
    @Override
1031
    public NameRelationField getOrthographicVariantField() {
1032
        return orthographicVariantField;
1033
    }
1034

    
1035
    @Override
1036
    public void enableMode(TaxonNamePopupEditorMode mode){
1037
            modesActive.add(mode);
1038
            updateFormOnModeChange();
1039
    }
1040

    
1041
    @Override
1042
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
1043
        return modesActive.contains(mode);
1044
    }
1045

    
1046
    @Override
1047
    public void disableMode(TaxonNamePopupEditorMode mode){
1048
        modesActive.remove(mode);
1049
        updateFormOnModeChange();
1050
    }
1051

    
1052
    /**
1053
     * updates UI in turn of mode changes if needed, that is when the bean has been set
1054
     * already.
1055
     */
1056
    private void updateFormOnModeChange() {
1057
        if(getBean() != null){
1058
            // need to update the ui
1059
            afterItemDataSourceSet();
1060
            if(!isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
1061
                updateFieldVisibility();
1062
            }
1063
        }
1064
    }
1065

    
1066
    @Override
1067
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
1068
        return modesActive;
1069
    }
1070

    
1071
    @Override
1072
    public CheckBox getBasionymToggle() {
1073
        return basionymToggle;
1074
    }
1075

    
1076
    @Override
1077
    public FilterableAnnotationsField getAnnotationsField() {
1078
        return annotationsListField;
1079
    }
1080

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

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

    
1121

    
1122
    /**
1123
     * @return the infraGenericEpithetField
1124
     */
1125
    @Override
1126
    public AbstractField<String> getInfraGenericEpithetField() {
1127
        return infraGenericEpithetField;
1128
    }
1129

    
1130
    /**
1131
     * @return the specificEpithetField
1132
     */
1133
    @Override
1134
    public AbstractField<String> getSpecificEpithetField() {
1135
        return specificEpithetField;
1136
    }
1137

    
1138
    /**
1139
     * @return the infraSpecificEpithetField
1140
     */
1141
    @Override
1142
    public AbstractField<String> getInfraSpecificEpithetField() {
1143
        return infraSpecificEpithetField;
1144
    }
1145

    
1146
    @Override
1147
    public CheckBox getOrthographicVariantToggle() {
1148
        return orthographicVariantToggle;
1149
    }
1150

    
1151
    @Override
1152
    public ElementCollectionField<NomenclaturalStatus> getNomStatusCollectionField(){
1153
        return nomStatusCollectionField;
1154
    }
1155

    
1156
}
(12-12/15)