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.NativeSelect;
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 NativeSelect 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 NativeSelect("Rank");
275
        rankSelect.setNullSelectionAllowed(false);
276
        rankSelect.setWidth(100, Unit.PERCENTAGE);
277
        addField(rankSelect, "rank", 0, row, 1, row);
278
        grid.setComponentAlignment(rankSelect, Alignment.TOP_RIGHT);
279

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

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

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

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

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

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

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

    
344

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

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

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

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

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

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

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

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

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

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

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

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

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

    
501
        // -----------------------------------------------------------------------------
502

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

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

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

    
516
        setAdvancedMode(false);
517

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

    
521
    }
522

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

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

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

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

    
566
    @Override
567
    protected void afterItemDataSourceSet() {
568

    
569

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

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

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

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

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

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

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

    
638
        TaxonNameDTO taxonName = getBean();
639

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

    
648

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

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

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

    
668
        }
669

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

    
679
        updateFieldVisibility();
680
    }
681

    
682

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

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

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

    
730
        return lastInferredAuthorshipState;
731
    }
732

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

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

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

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

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

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

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

    
827
        basionymsComboboxSelect.setVisible(withBasionymSection);
828

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

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

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

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

    
853

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

    
861

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
995

    
996

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

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

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

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

    
1026

    
1027
}
(11-11/14)