Project

General

Profile

Download (41.4 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.vaadin.view.name;
10

    
11
import java.util.Collection;
12
import java.util.EnumSet;
13
import java.util.HashMap;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.UUID;
17

    
18
import org.apache.commons.lang3.BooleanUtils;
19
import org.springframework.context.annotation.Scope;
20
import org.springframework.security.core.GrantedAuthority;
21

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

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

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

    
72
    private static final long serialVersionUID = -7037436241474466359L;
73

    
74
    private final static int GRID_COLS = 4;
75

    
76
    private final static int GRID_ROWS = 19;
77

    
78
    private static final boolean HAS_BASIONYM_DEFAULT = false;
79

    
80
    private AbstractField<String> genusOrUninomialField;
81

    
82
    private AbstractField<String> infraGenericEpithetField;
83

    
84
    private AbstractField<String> specificEpithetField;
85

    
86
    private AbstractField<String> infraSpecificEpithetField;
87

    
88
    private SwitchableTextField fullTitleCacheFiled;
89

    
90
    private SwitchableTextField protectedNameCacheField;
91

    
92
    private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
93

    
94
    private TextField nomenclaturalReferenceDetail;
95

    
96
    private TeamOrPersonField exBasionymAuthorshipField;
97

    
98
    private TeamOrPersonField basionymAuthorshipField;
99

    
100
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
101

    
102
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> replacedSynonymsComboboxSelect;
103

    
104
    private NameRelationField validationField;
105

    
106
    private NameRelationField orthographicVariantField;
107

    
108
    private CheckBox basionymToggle;
109

    
110
    private CheckBox replacedSynonymsToggle;
111

    
112
    private CheckBox validationToggle;
113

    
114
    private CheckBox orthographicVariantToggle;
115

    
116
    private ListSelect rankSelect;
117

    
118
    private TeamOrPersonField combinationAuthorshipField;
119

    
120
    private TeamOrPersonField exCombinationAuthorshipField;
121

    
122
    private EnumSet<TaxonNamePopupEditorMode> modesActive = EnumSet.noneOf(TaxonNamePopupEditorMode.class);
123

    
124
    private Boolean isInferredCombinationAuthorship = null;
125

    
126
    private Boolean isInferredBasionymAuthorship = null;
127

    
128
    private Boolean isInferredExBasionymAuthorship = null;
129

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

    
132
    private Boolean isInferredExCombinationAuthorship;
133

    
134
    private int specificEpithetFieldRow;
135

    
136
    private ValueChangeListener updateFieldVisibilityListener = e -> updateFieldVisibility();
137

    
138
    private FilterableAnnotationsField annotationsListField;
139

    
140
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
141

    
142
    private int genusOrUninomialRow;
143

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

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

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

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

    
181

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

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

    
197
    }
198

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

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

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

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

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

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

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

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

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

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

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

    
261
         ** ViralName attributes **
262
         - acronym
263

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

    
273
        int row = 0;
274

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

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

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

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

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

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

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

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

    
346

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

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

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

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

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

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

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

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

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

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

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

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

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

    
503
        // -----------------------------------------------------------------------------
504

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

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

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

    
518
        setAdvancedMode(false);
519

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

    
523
    }
524

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

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

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

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

    
568
    @Override
569
    protected void afterItemDataSourceSet() {
570

    
571

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

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

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

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

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

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

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

    
640
        TaxonNameDTO taxonName = getBean();
641

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

    
650

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

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

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

    
670
        }
671

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

    
681
        updateFieldVisibility();
682
    }
683

    
684

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

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

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

    
732
        return lastInferredAuthorshipState;
733
    }
734

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

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

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

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

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

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

    
821
        specificEpithetField.setVisible(isSpeciesOrBelow);
822
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
823
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
824

    
825
        basionymsComboboxSelect.setVisible(withBasionymSection);
826

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

    
831
        validationField.setVisible(withValidationSection);
832
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
833

    
834
        orthographicVariantField.setVisible(withOrthographicCorrectionSection);
835

    
836
//        if(taxonName != null){
837
//            if(modesActive.contains(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
838
//            }
839
//        }
840

    
841
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
842
        specificEpithetField.setVisible(isSpeciesOrBelow);
843
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
844
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
845
    }
846

    
847

    
848
    @Override
849
    public void cancel() {
850
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
851
        rankSelect.removeValueChangeListener(updateFieldVisibilityListener);
852
        super.cancel();
853
    }
854

    
855
    /**
856
     * {@inheritDoc}
857
     */
858
    @Override
859
    public boolean allowAnonymousAccess() {
860
        return false;
861
    }
862

    
863
    /**
864
     * {@inheritDoc}
865
     */
866
    @Override
867
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
868
        return null;
869
    }
870

    
871
    /**
872
     * {@inheritDoc}
873
     */
874
    @Override
875
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
876
        return nomReferenceCombobox;
877
    }
878

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

    
887
    /**
888
     * {@inheritDoc}
889
     */
890
    @Override
891
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
892
        return replacedSynonymsComboboxSelect;
893
    }
894

    
895
    /**
896
     * {@inheritDoc}
897
     */
898
    @Override
899
    public ListSelect getRankSelect() {
900
        return rankSelect;
901
    }
902

    
903
    /**
904
     * {@inheritDoc}
905
     */
906
    @Override
907
    public AbstractField<String> getGenusOrUninomialField(){
908
        return genusOrUninomialField;
909
    }
910

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

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

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

    
935
    /**
936
     * @return the exCombinationAuthorshipField
937
     */
938
    @Override
939
    public TeamOrPersonField getExCombinationAuthorshipField() {
940
        return exCombinationAuthorshipField;
941
    }
942

    
943
    @Override
944
    public NameRelationField getValidationField(){
945
        return validationField;
946
    }
947

    
948
    @Override
949
    public NameRelationField getOrthographicVariantField() {
950
        return orthographicVariantField;
951
    }
952

    
953
    @Override
954
    public void enableMode(TaxonNamePopupEditorMode mode){
955
            modesActive.add(mode);
956
    }
957

    
958
    @Override
959
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
960
        return modesActive.contains(mode);
961
    }
962

    
963
    @Override
964
    public void disableMode(TaxonNamePopupEditorMode mode){
965
        modesActive.remove(mode);
966
    }
967

    
968
    @Override
969
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
970
        return modesActive;
971
    }
972

    
973
    @Override
974
    public CheckBox getBasionymToggle() {
975
        return basionymToggle;
976
    }
977

    
978
    @Override
979
    public FilterableAnnotationsField getAnnotationsField() {
980
        return annotationsListField;
981
    }
982

    
983
    /**
984
     * {@inheritDoc}
985
     */
986
    @Override
987
    public void setReadOnly(boolean readOnly) {
988
        boolean basionymToggleReadonly = basionymToggle.isReadOnly();
989
        boolean validationToggleReadonly = validationToggle.isReadOnly();
990
        super.setReadOnly(readOnly);
991
        combinationAuthorshipField.setEditorReadOnly(readOnly);
992
        exCombinationAuthorshipField.setEditorReadOnly(readOnly);
993
        basionymAuthorshipField.setEditorReadOnly(readOnly);
994
        exBasionymAuthorshipField.setEditorReadOnly(readOnly);
995
        // preserve old readonly states if they were true
996
        if(basionymToggleReadonly){
997
            basionymToggle.setReadOnly(true);
998
        }
999
        if(validationToggleReadonly){
1000
            validationToggle.setReadOnly(true);
1001
        }
1002
    }
1003

    
1004

    
1005

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

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

    
1022
    /**
1023
     * @return the infraSpecificEpithetField
1024
     */
1025
    @Override
1026
    public AbstractField<String> getInfraSpecificEpithetField() {
1027
        return infraSpecificEpithetField;
1028
    }
1029

    
1030

    
1031
}
(10-10/13)