Project

General

Profile

Download (41.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.EnumSet;
12
import java.util.HashMap;
13
import java.util.List;
14
import java.util.Map;
15
import java.util.UUID;
16

    
17
import org.apache.commons.lang3.BooleanUtils;
18
import org.springframework.context.annotation.Scope;
19

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

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

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

    
69
    private static final long serialVersionUID = -7037436241474466359L;
70

    
71
    private final static int GRID_COLS = 4;
72

    
73
    private final static int GRID_ROWS = 19;
74

    
75
    private static final boolean HAS_BASIONYM_DEFAULT = false;
76

    
77
    private AbstractField<String> genusOrUninomialField;
78

    
79
    private AbstractField<String> infraGenericEpithetField;
80

    
81
    private AbstractField<String> specificEpithetField;
82

    
83
    private AbstractField<String> infraSpecificEpithetField;
84

    
85
    private SwitchableTextField fullTitleCacheFiled;
86

    
87
    private SwitchableTextField protectedNameCacheField;
88

    
89
    private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
90

    
91
    private TextField nomenclaturalReferenceDetail;
92

    
93
    private TeamOrPersonField exBasionymAuthorshipField;
94

    
95
    private TeamOrPersonField basionymAuthorshipField;
96

    
97
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
98

    
99
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> replacedSynonymsComboboxSelect;
100

    
101
    private NameRelationField validationField;
102

    
103
    private NameRelationField orthographicVariantField;
104

    
105
    private CheckBox basionymToggle;
106

    
107
    private CheckBox replacedSynonymsToggle;
108

    
109
    private CheckBox validationToggle;
110

    
111
    private CheckBox orthographicVariantToggle;
112

    
113
    private ListSelect rankSelect;
114

    
115
    private TeamOrPersonField combinationAuthorshipField;
116

    
117
    private TeamOrPersonField exCombinationAuthorshipField;
118

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

    
121
    private Boolean isInferredCombinationAuthorship = null;
122

    
123
    private Boolean isInferredBasionymAuthorship = null;
124

    
125
    private Boolean isInferredExBasionymAuthorship = null;
126

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

    
129
    private Boolean isInferredExCombinationAuthorship;
130

    
131
    private int specificEpithetFieldRow;
132

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

    
135
    private FilterableAnnotationsField annotationsListField;
136

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

    
139
    private int genusOrUninomialRow;
140

    
141
    private OrthographicCorrectionReferenceValidator orthographicCorrectionValidator;
142

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

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

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

    
172
    /**
173
     * {@inheritDoc}
174
     */
175
    @Override
176
    public String getWindowCaption() {
177
        return "Name editor";
178
    }
179

    
180

    
181
    /**
182
     * {@inheritDoc}
183
     */
184
    @Override
185
    public int getWindowWidth() {
186
        return 800;
187
    }
188

    
189
    /**
190
     * {@inheritDoc}
191
     */
192
    @Override
193
    public void focusFirst() {
194
        // titleField.focus();
195

    
196
    }
197

    
198
    /**
199
     * {@inheritDoc}
200
     */
201
    @Override
202
    protected String getDefaultComponentStyles() {
203
        return "tiny";
204
    }
205

    
206
    /**
207
     * {@inheritDoc}
208
     */
209
    @Override
210
    protected void initContent() {
211

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

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

    
228
         - fullTitleCache + protectedFullTitleCache -> SwitchableTextField : ADVANCED_MODE
229
         - nameCache + protectedNameCache -> SwitchableTextField : ADVANCED_MODE
230

    
231
         - homotypicalGroup -> hidden
232
         - typeDesignations -> hidden
233
         - descriptions -> hidden
234
         - taxonBases -> hidden
235
         - registrations -> hidden
236

    
237
         - relationsFromThisName-> TODO implement later
238
         - relationsToThisName -> TODO implement later
239

    
240
         - genusOrUninomial -> textField
241
         - infraGenericEpithet  -> textField
242
         - specificEpithet  -> textField
243
         - infraSpecificEpithet  -> textField
244

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

    
251
         - status -> TODO field
252
         - monomHybrid -> TODO implement hybrids later
253
         - binomHybrid -> TODO implement hybrids later
254
         - trinomHybrid -> TODO implement hybrids later
255

    
256
         - hybridParentRelations -> TODO implement hybrids later
257
         - hybridChildRelations -> TODO implement hybrids later
258
         - hybridFormula -> TODO implement hybrids later
259

    
260
         ** ViralName attributes **
261
         - acronym
262

    
263
         ** BacterialName attributes **
264
         - subGenusAuthorship
265
         - nameApprobation
266
         - breed
267
         - publicationYear
268
         - originalPublicationYear
269
         - cultivarName
270
        */
271

    
272
        int row = 0;
273

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

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

    
288
        replacedSynonymsToggle = new CheckBox("With replaced synonym");
289
        grid.addComponent(replacedSynonymsToggle, 1, row);
290
        grid.setComponentAlignment(replacedSynonymsToggle, Alignment.BOTTOM_LEFT);
291

    
292
        validationToggle = new CheckBox("Validation");
293
        grid.addComponent(validationToggle, 2, row);
294
        grid.setComponentAlignment(validationToggle, Alignment.BOTTOM_LEFT);
295

    
296
        orthographicVariantToggle = new CheckBox("Orthographic variant");
297
        grid.addComponent(orthographicVariantToggle, 3, row);
298
        grid.setComponentAlignment(orthographicVariantToggle, Alignment.BOTTOM_LEFT);
299

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

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

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

    
345

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

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

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

    
365
            Object fieldValue = e.getSource().getValue();
366
            UUID beanUuid = null;
367
            if(fieldValue != null){
368
                beanUuid = ((CdmBase)fieldValue).getUuid();
369

    
370
            }
371
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
372
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
373
        });
374
        grid.setComponentAlignment(basionymsComboboxSelect, Alignment.TOP_RIGHT);
375

    
376
        row++;
377
        basionymAuthorshipField = new TeamOrPersonField("Basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
378
        basionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
379
        addField(basionymAuthorshipField, "basionymAuthorship", 0, row, GRID_COLS-1, row);
380
        row++;
381
        exBasionymAuthorshipField = new TeamOrPersonField("Ex-basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
382
        exBasionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
383
        addField(exBasionymAuthorshipField, "exBasionymAuthorship", 0, row, GRID_COLS-1, row);
384

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

    
395
            Object fieldValue = e.getSource().getValue();
396
            UUID beanUuid = null;
397
            if(fieldValue != null){
398
                beanUuid = ((CdmBase)fieldValue).getUuid();
399

    
400
            }
401
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
402
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
403
        });
404
        grid.setComponentAlignment(replacedSynonymsComboboxSelect, Alignment.TOP_RIGHT);
405

    
406
        // --------------- Validation
407
        row++;
408
        validationField = new NameRelationField("Validation", "Validated name", Direction.relatedTo, NameRelationshipType.VALIDATED_BY_NAME());
409
        validationField.setWidth(100, Unit.PERCENTAGE);
410
        ToOneRelatedEntityCombobox<TaxonName> validatedNameComboBox = validationField.getRelatedNameComboBox();
411
        validatedNameComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
412
                this,
413
                new TaxonNameEditorAction(EditorActionType.ADD, null, validatedNameComboBox, this)
414
                ));
415
        validatedNameComboBox.addClickListenerEditEntity(e -> {
416
            if(validatedNameComboBox.getValue() != null){
417
                getViewEventBus().publish(this,
418
                    new TaxonNameEditorAction(
419
                            EditorActionType.EDIT,
420
                            validatedNameComboBox.getValue().getUuid(),
421
                            e.getButton(),
422
                            validatedNameComboBox,
423
                            this)
424
                );
425
            }
426
        });
427
        ToOneRelatedEntityCombobox<Reference> validationCitatonComboBox = validationField.getCitatonComboBox();
428
        validationCitatonComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
429
                // NOTE: adding new references is currently not allowed for name relations, see NameRelationField!!
430
                this,
431
                new ReferenceEditorAction(EditorActionType.ADD, null, validationCitatonComboBox, this)
432
                ));
433
        validationCitatonComboBox.addClickListenerEditEntity(e -> {
434
            if(validationCitatonComboBox.getValue() != null){
435
                getViewEventBus().publish(this,
436
                    new ReferenceEditorAction(
437
                            EditorActionType.EDIT,
438
                            validationCitatonComboBox.getValue().getUuid(),
439
                            e.getButton(),
440
                            validationCitatonComboBox,
441
                            this)
442
                );
443
            }
444
        });
445
        addField(validationField, "validationFor", 0, row, 3, row);
446
        grid.setComponentAlignment(validationField, Alignment.TOP_RIGHT);
447

    
448
        // ------- Orthographic Variant (Correction)
449
        row++;
450
        orthographicVariantField = new NameRelationField("Orthographic variant", "Name variant", Direction.relatedTo, NameRelationshipType.ORTHOGRAPHIC_VARIANT());
451
        orthographicVariantField.setWidth(100, Unit.PERCENTAGE);
452
        // corrected name must have same
453
        ToOneRelatedEntityCombobox<TaxonName> orthographicVariantCombobox = orthographicVariantField.getRelatedNameComboBox();
454
        orthographicVariantCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
455
                this,
456
                new TaxonNameEditorAction(EditorActionType.ADD, null, orthographicVariantCombobox, this)
457
                ));
458
        orthographicVariantCombobox.addClickListenerEditEntity(e -> {
459
            if(orthographicVariantCombobox.getValue() != null){
460
                getViewEventBus().publish(this,
461
                    new TaxonNameEditorAction(
462
                            EditorActionType.EDIT,
463
                            orthographicVariantCombobox.getValue().getUuid(),
464
                            e.getButton(),
465
                            orthographicVariantCombobox,
466
                            this)
467
                );
468
            }
469
        });
470
        ToOneRelatedEntityCombobox<Reference> orthographicCorrectionCitatonComboBox = orthographicVariantField.getCitatonComboBox();
471
        orthographicCorrectionCitatonComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
472
                // NOTE: adding new references is currently not allowed for name relations, see NameRelationField!!
473
                this,
474
                new ReferenceEditorAction(EditorActionType.ADD, null, orthographicCorrectionCitatonComboBox, this)
475
                ));
476
        orthographicCorrectionCitatonComboBox.addClickListenerEditEntity(e -> {
477
            if(orthographicCorrectionCitatonComboBox.getValue() != null){
478
                getViewEventBus().publish(this,
479
                    new ReferenceEditorAction(
480
                            EditorActionType.EDIT,
481
                            orthographicCorrectionCitatonComboBox.getValue().getUuid(),
482
                            e.getButton(),
483
                            orthographicCorrectionCitatonComboBox,
484
                            this)
485
                );
486
            }
487
        });
488
        addField(orthographicVariantField, "orthographicVariant", 0, row, 3, row);
489
        grid.setComponentAlignment(orthographicVariantField, Alignment.TOP_RIGHT);
490

    
491
        row++;
492
        exCombinationAuthorshipField = new TeamOrPersonField("Ex-combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
493
        exCombinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
494
        addField(exCombinationAuthorshipField, "exCombinationAuthorship", 0, row, GRID_COLS-1, row);
495

    
496
        row++;
497
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
498
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
499
        annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
500
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
501

    
502
        // -----------------------------------------------------------------------------
503

    
504
        setAdvancedModeEnabled(true);
505
        registerAdvancedModeComponents(fullTitleCacheFiled, protectedNameCacheField);
506

    
507
        registerAdvancedModeComponents(combinationAuthorshipField);
508
        registerAdvancedModeComponents(basionymAuthorshipField);
509
        registerAdvancedModeComponents(exBasionymAuthorshipField);
510
        registerAdvancedModeComponents(exCombinationAuthorshipField);
511

    
512
        registerAdvancedModeComponents(combinationAuthorshipField.getCachFields());
513
        registerAdvancedModeComponents(exCombinationAuthorshipField.getCachFields());
514
        registerAdvancedModeComponents(basionymAuthorshipField.getCachFields());
515
        registerAdvancedModeComponents(exBasionymAuthorshipField.getCachFields());
516

    
517
        setAdvancedMode(false);
518

    
519
        //TODO remove below line once #7858 is fixed
520
        withDeleteButton(false);
521

    
522
    }
523

    
524
    protected TeamOrPersonBase inferBasiomynAuthors() {
525
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
526
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
527
            TaxonName basionym = basionyms.get(0);
528
            if(basionym.getCombinationAuthorship() != null){
529
                return basionym.getCombinationAuthorship();
530
            } else if(basionym.getNomenclaturalReference() != null){
531
                return basionym.getNomenclaturalReference().getAuthorship();
532
            }
533
        }
534
        return null;
535
    }
536

    
537
    protected TeamOrPersonBase inferExBasiomynAuthors() {
538
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
539
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
540
            TaxonName basionym = basionyms.get(0);
541
                return basionym.getExCombinationAuthorship();
542
        }
543
        return null;
544
    }
545

    
546
    protected TeamOrPersonBase inferCombinationAuthors() {
547
        Reference nomRef = nomReferenceCombobox.getValue();
548
        if(nomRef != null) {
549
            return nomRef.getAuthorship();
550
        }
551
        return null;
552
    }
553

    
554
    protected TeamOrPersonBase inferExCombinationAuthors() {
555
        NameRelationshipDTO nameRelationDTO = validationField.getValue();
556
        if(nameRelationDTO != null && nameRelationDTO.getOtherName() != null){
557
            TaxonName validatedName = nameRelationDTO.getOtherName();
558
            if(validatedName.getCombinationAuthorship() != null) {
559
                return validatedName.getCombinationAuthorship();
560
            } else if(validatedName.getNomenclaturalReference() != null){
561
                return validatedName.getNomenclaturalReference().getAuthorship();
562
            }
563
        }
564
        return null;
565
    }
566

    
567
    @Override
568
    protected void afterItemDataSourceSet() {
569

    
570

    
571
        rankSelect.addValueChangeListener(updateFieldVisibilityListener);
572
        basionymToggle.addValueChangeListener(e -> {
573
            updateAuthorshipFields();
574
        });
575
        validationToggle.addValueChangeListener(e -> {
576
            updateAuthorshipFields();
577
            });
578
        replacedSynonymsToggle.addValueChangeListener(e -> {
579
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
580
            replacedSynonymsComboboxSelect.setVisible(enable);
581
        });
582
        orthographicVariantToggle.addValueChangeListener(e -> {
583
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
584
            orthographicVariantField.setVisible(enable);
585
        });
586

    
587
        TaxonNameDTO taxonNameDTO = getBean();
588
        boolean showBasionymSection = taxonNameDTO.getBasionyms().size() > 0
589
                || taxonNameDTO.getBasionymAuthorship() != null
590
                || taxonNameDTO.getExBasionymAuthorship() != null;
591
        basionymToggle.setValue(showBasionymSection);
592
        basionymToggle.setReadOnly(showBasionymSection);
593

    
594
        boolean showReplacedSynonyms = taxonNameDTO.getReplacedSynonyms().size() > 0;
595
        replacedSynonymsToggle.setValue(showReplacedSynonyms);
596
        replacedSynonymsToggle.setReadOnly(showReplacedSynonyms);
597
        replacedSynonymsComboboxSelect.setVisible(showReplacedSynonyms);
598

    
599
        boolean showValidationSection = taxonNameDTO.getValidationFor() != null || taxonNameDTO.getExCombinationAuthorship() != null;
600
        validationToggle.setValue(showValidationSection);
601
        validationToggle.setReadOnly(showValidationSection);
602

    
603
        boolean showOrthographicCorrectionSection = taxonNameDTO.getOrthographicVariant() != null;
604
        orthographicVariantToggle.setValue(showOrthographicCorrectionSection);
605
        orthographicVariantToggle.setReadOnly(showOrthographicCorrectionSection);
606

    
607
        if(isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
608
            updateAuthorshipFields();
609
        }
610
        if(isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY) && getBean().getNomenclaturalReference() != null) {
611
            nomReferenceCombobox.setDescription("Selection limited to nomenclatural reference and parts of it.");
612
        }
613
        if(isModeEnabled(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE)) {
614
            if(combinationAuthorshipField.getValue() == null){
615
                nomReferenceCombobox.setRequired(true);
616
                nomReferenceCombobox.setImmediate(true);
617
            } else {
618
                combinationAuthorshipField.addValueChangeListener(e -> {
619
                    if(e.getProperty().getValue() == null){
620
                        nomReferenceCombobox.setRequired(true);
621
                        nomReferenceCombobox.setImmediate(true);
622
                    }
623
                });
624
            }
625
        }
626
    }
627

    
628
    /**
629
     * Updates all authorship fields if the an authorship field is empty this method attempts to infer the
630
     * authors from the related nomenclatural reference or taxon name.
631
     * <p>
632
     * Finally the {@link #updateFieldVisibility()} is invoked.
633
     *
634
     * @param taxonName
635
     */
636
    @Override
637
    public void updateAuthorshipFields() {
638

    
639
        TaxonNameDTO taxonName = getBean();
640

    
641
        // ------------- CombinationAuthors
642
        isInferredCombinationAuthorship = updateAuthorshipFieldData(
643
                taxonName.getCombinationAuthorship(),
644
                inferCombinationAuthors(),
645
                combinationAuthorshipField,
646
                nomReferenceCombobox.getSelect(),
647
                isInferredCombinationAuthorship);
648

    
649

    
650
        // ------------- Basionym and ExBasionymAuthors
651
        if(BooleanUtils.isTrue(basionymToggle.getValue())){
652

    
653
            isInferredBasionymAuthorship = updateAuthorshipFieldData(
654
                    taxonName.getBasionymAuthorship(),
655
                    inferBasiomynAuthors(),
656
                    basionymAuthorshipField,
657
                    basionymsComboboxSelect,
658
                    isInferredBasionymAuthorship
659
                    );
660

    
661
            isInferredExBasionymAuthorship = updateAuthorshipFieldData(
662
                    taxonName.getExBasionymAuthorship(),
663
                    inferExBasiomynAuthors(),
664
                    exBasionymAuthorshipField,
665
                    basionymsComboboxSelect,
666
                    isInferredExBasionymAuthorship
667
                    );
668

    
669
        }
670

    
671
        // ------------- Validation and ExCombinationAuthors
672
        isInferredExCombinationAuthorship = updateAuthorshipFieldData(
673
                taxonName.getExCombinationAuthorship(),
674
                inferExCombinationAuthors(),
675
                exCombinationAuthorshipField,
676
                validationField.getRelatedNameComboBox(),
677
                isInferredExCombinationAuthorship
678
                );
679

    
680
        updateFieldVisibility();
681
    }
682

    
683

    
684
    /**
685
     *
686
     * @param authorship
687
     *    the value of the taxonName authorship field
688
     * @param inferredAuthors
689
     *    the value inferred from other fields which may be set as authorship to the taxon name
690
     * @param authorshipField
691
     *    the ui element to edit the taxonName authorship field
692
     * @param updateTriggerField
693
     * @param lastInferredAuthorshipState
694
     * @return
695
     */
696
    protected Boolean updateAuthorshipFieldData(TeamOrPersonBase<?> authorship, TeamOrPersonBase inferredAuthors,
697
            TeamOrPersonField authorshipField, AbstractField updateTriggerField,
698
            Boolean lastInferredAuthorshipState) {
699

    
700
        if(authorship == null){
701
            authorshipField.setValue(inferredAuthors);
702
            lastInferredAuthorshipState = true;
703
        } else {
704
            boolean authorshipMatch = authorship == inferredAuthors;
705
            if(lastInferredAuthorshipState == null){
706
                // initialization of authorshipState, this comes only into account when the editor is just being initialized
707
                lastInferredAuthorshipState = authorshipMatch;
708
            }
709
            if(!authorshipMatch && lastInferredAuthorshipState){
710
                // update the combinationAuthorshipField to follow changes of the nomenclatural reference in case it was autofilled before
711
                authorshipField.setValue(inferredAuthors);
712
                lastInferredAuthorshipState = true;
713
            }
714
        }
715

    
716
        if(updateTriggerField != null){
717
            // IMPORTANT!
718
            // this ChangeListener must be added at this very late point in the editor lifecycle so that it is called after
719
            // the ToOneRelatedEntityReloader which may have been added to the updateTriggerField in the presenters handleViewEntered() method.
720
            // Otherwise we risk multiple representation problems in the hibernate session
721
            if(!authorshipUpdateListeners.containsKey(updateTriggerField)){
722
                ValueChangeListener listener = e ->  {
723
                    logger.debug(" value changed #2");
724
                    updateAuthorshipFields();
725
                };
726
                updateTriggerField.addValueChangeListener(listener);
727
                authorshipUpdateListeners.put(updateTriggerField, listener);
728
            }
729
        }
730

    
731
        return lastInferredAuthorshipState;
732
    }
733

    
734
    /**
735
     * @param rank
736
     * @return
737
     */
738
    private void updateFieldVisibility() {
739

    
740
        // TODO use getField() instead and remove field references
741
        Rank rank = (Rank) rankSelect.getValue();
742

    
743
        boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES());
744
        Boolean withBasionymSection = BooleanUtils.isTrue(basionymToggle.getValue());
745
        Boolean withValidationSection = BooleanUtils.isTrue(validationToggle.getValue());
746
        Boolean withOrthographicCorrectionSection = BooleanUtils.isTrue(orthographicVariantToggle.getValue());
747

    
748
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
749
            if(isSpeciesOrBelow) {
750
                if(TextField.class.isAssignableFrom(genusOrUninomialField.getClass())){
751
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
752
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
753
                            this,
754
                            new TaxonNameEditorActionStrRep(
755
                                    EditorActionType.ADD,
756
                                    e.getButton(),
757
                                    combobox,
758
                                    this)
759
                        ));
760
                    combobox.addClickListenerEditEntity(e -> {
761
                        if(combobox.getValue() != null){
762
                            getViewEventBus().publish(this,
763
                                new TaxonNameEditorActionStrRep(
764
                                        EditorActionType.EDIT,
765
                                        combobox.getIdForValue(),
766
                                        e.getButton(),
767
                                        combobox,
768
                                        this)
769
                            );
770
                        }
771
                    });
772
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, combobox, 0, genusOrUninomialRow, 1, genusOrUninomialRow);
773
                }
774
            } else {
775
                if(WeaklyRelatedEntityCombobox.class.isAssignableFrom(genusOrUninomialField.getClass())) {
776
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, new TextFieldNFix(), 0, genusOrUninomialRow, 1, genusOrUninomialRow);
777
                }
778
            }
779
        }
780

    
781
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
782
            if(rank.isInfraSpecific()) {
783
                if(TextField.class.isAssignableFrom(specificEpithetField.getClass())) {
784
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
785
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, combobox, 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
786
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
787
                            this,
788
                            new TaxonNameEditorActionStrRep(EditorActionType.ADD, e.getButton(), combobox, this)
789
                        ));
790
                    combobox.addClickListenerEditEntity(e -> {
791
                        if(combobox.getValue() != null){
792
                            getViewEventBus().publish(this,
793
                                new TaxonNameEditorActionStrRep(
794
                                        EditorActionType.EDIT,
795
                                        combobox.getIdForValue(),
796
                                        e.getButton(),
797
                                        combobox,
798
                                        this)
799
                            );
800
                        }
801
                    });
802
                }
803
            } else {
804
                if(WeaklyRelatedEntityCombobox.class.isAssignableFrom(specificEpithetField.getClass())) {
805
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, new TextFieldNFix(), 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
806
               }
807
            }
808
        }
809

    
810
        if(isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
811
            orthographicVariantField.setCaption("Orthographic correction");
812
            orthographicVariantField.getRelatedNameComboBox().setCaption("Incorrect name");
813
            orthographicVariantToggle.setCaption("Orthographic correction");
814
        } else {
815
            orthographicVariantField.setCaption("Orthographic variant");
816
            orthographicVariantField.getRelatedNameComboBox().setCaption("Name variant");
817
            orthographicVariantToggle.setCaption("Orthographic variant");
818
        }
819

    
820
        genusOrUninomialField.setRequired(true);
821
        specificEpithetField.setVisible(isSpeciesOrBelow);
822
        specificEpithetField.setRequired(isSpeciesOrBelow);
823
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
824
        infraSpecificEpithetField.setRequired(rank.isInfraSpecific());
825
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
826
        infraGenericEpithetField.setRequired(rank.isInfraGeneric());
827

    
828
        basionymsComboboxSelect.setVisible(withBasionymSection);
829

    
830
        combinationAuthorshipField.setVisible(isInferredCombinationAuthorship != null && !isInferredCombinationAuthorship);
831
        basionymAuthorshipField.setVisible(withBasionymSection && isInferredBasionymAuthorship != null && !isInferredBasionymAuthorship);
832
        exBasionymAuthorshipField.setVisible(withBasionymSection && isInferredExBasionymAuthorship != null && !isInferredExBasionymAuthorship);
833

    
834
        validationField.setVisible(withValidationSection);
835
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
836

    
837
        orthographicVariantField.setVisible(withOrthographicCorrectionSection);
838
        if(withOrthographicCorrectionSection){
839
            orthographicCorrectionValidator = new OrthographicCorrectionReferenceValidator(nomReferenceCombobox);
840
            orthographicVariantField.addValidator(orthographicCorrectionValidator);
841
        } else {
842
            if(orthographicCorrectionValidator  != null){
843
                orthographicVariantField.removeValidator(orthographicCorrectionValidator);
844
                orthographicVariantField = null;
845
            }
846
        }
847

    
848
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
849
        specificEpithetField.setVisible(isSpeciesOrBelow);
850
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
851
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
852
    }
853

    
854

    
855
    @Override
856
    public void cancel() {
857
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
858
        rankSelect.removeValueChangeListener(updateFieldVisibilityListener);
859
        super.cancel();
860
    }
861

    
862

    
863
    /**
864
     * {@inheritDoc}
865
     */
866
    @Override
867
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
868
        return nomReferenceCombobox;
869
    }
870

    
871
    /**
872
     * {@inheritDoc}
873
     */
874
    @Override
875
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
876
        return basionymsComboboxSelect;
877
    }
878

    
879
    /**
880
     * {@inheritDoc}
881
     */
882
    @Override
883
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
884
        return replacedSynonymsComboboxSelect;
885
    }
886

    
887
    /**
888
     * {@inheritDoc}
889
     */
890
    @Override
891
    public ListSelect getRankSelect() {
892
        return rankSelect;
893
    }
894

    
895
    /**
896
     * {@inheritDoc}
897
     */
898
    @Override
899
    public AbstractField<String> getGenusOrUninomialField(){
900
        return genusOrUninomialField;
901
    }
902

    
903
    /**
904
     * @return the exBasionymAuthorshipField
905
     */
906
    @Override
907
    public TeamOrPersonField getExBasionymAuthorshipField() {
908
        return exBasionymAuthorshipField;
909
    }
910

    
911
    /**
912
     * @return the basionymAuthorshipField
913
     */
914
    @Override
915
    public TeamOrPersonField getBasionymAuthorshipField() {
916
        return basionymAuthorshipField;
917
    }
918

    
919
    /**
920
     * @return the combinationAuthorshipField
921
     */
922
    @Override
923
    public TeamOrPersonField getCombinationAuthorshipField() {
924
        return combinationAuthorshipField;
925
    }
926

    
927
    /**
928
     * @return the exCombinationAuthorshipField
929
     */
930
    @Override
931
    public TeamOrPersonField getExCombinationAuthorshipField() {
932
        return exCombinationAuthorshipField;
933
    }
934

    
935
    @Override
936
    public NameRelationField getValidationField(){
937
        return validationField;
938
    }
939

    
940
    @Override
941
    public NameRelationField getOrthographicVariantField() {
942
        return orthographicVariantField;
943
    }
944

    
945
    @Override
946
    public void enableMode(TaxonNamePopupEditorMode mode){
947
            modesActive.add(mode);
948
    }
949

    
950
    @Override
951
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
952
        return modesActive.contains(mode);
953
    }
954

    
955
    @Override
956
    public void disableMode(TaxonNamePopupEditorMode mode){
957
        modesActive.remove(mode);
958
    }
959

    
960
    @Override
961
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
962
        return modesActive;
963
    }
964

    
965
    @Override
966
    public CheckBox getBasionymToggle() {
967
        return basionymToggle;
968
    }
969

    
970
    @Override
971
    public FilterableAnnotationsField getAnnotationsField() {
972
        return annotationsListField;
973
    }
974

    
975
    /**
976
     * {@inheritDoc}
977
     */
978
    @Override
979
    public void setReadOnly(boolean readOnly) {
980
        boolean basionymToggleReadonly = basionymToggle.isReadOnly();
981
        boolean validationToggleReadonly = validationToggle.isReadOnly();
982
        super.setReadOnly(readOnly);
983
        combinationAuthorshipField.setEditorReadOnly(readOnly);
984
        exCombinationAuthorshipField.setEditorReadOnly(readOnly);
985
        basionymAuthorshipField.setEditorReadOnly(readOnly);
986
        exBasionymAuthorshipField.setEditorReadOnly(readOnly);
987
        // preserve old readonly states if they were true
988
        if(basionymToggleReadonly){
989
            basionymToggle.setReadOnly(true);
990
        }
991
        if(validationToggleReadonly){
992
            validationToggle.setReadOnly(true);
993
        }
994
    }
995

    
996

    
997

    
998
    /**
999
     * @return the infraGenericEpithetField
1000
     */
1001
    @Override
1002
    public AbstractField<String> getInfraGenericEpithetField() {
1003
        return infraGenericEpithetField;
1004
    }
1005

    
1006
    /**
1007
     * @return the specificEpithetField
1008
     */
1009
    @Override
1010
    public AbstractField<String> getSpecificEpithetField() {
1011
        return specificEpithetField;
1012
    }
1013

    
1014
    /**
1015
     * @return the infraSpecificEpithetField
1016
     */
1017
    @Override
1018
    public AbstractField<String> getInfraSpecificEpithetField() {
1019
        return infraSpecificEpithetField;
1020
    }
1021

    
1022
    @Override
1023
    public CheckBox getOrthographicVariantToggle() {
1024
        return orthographicVariantToggle;
1025
    }
1026

    
1027

    
1028
}
(11-11/14)