Project

General

Profile

Download (37.5 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.shared.ui.label.ContentMode;
25
import com.vaadin.spring.annotation.SpringComponent;
26
import com.vaadin.ui.AbstractField;
27
import com.vaadin.ui.Alignment;
28
import com.vaadin.ui.CheckBox;
29
import com.vaadin.ui.GridLayout;
30
import com.vaadin.ui.Label;
31
import com.vaadin.ui.ListSelect;
32
import com.vaadin.ui.TextField;
33

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

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

    
74
    private static final long serialVersionUID = -7037436241474466359L;
75

    
76
    private final static int GRID_COLS = 4;
77

    
78
    private final static int GRID_ROWS = 18;
79

    
80
    private static final boolean HAS_BASIONYM_DEFAULT = false;
81

    
82
    private AbstractField<String> genusOrUninomialField;
83

    
84
    private AbstractField<String> infraGenericEpithetField;
85

    
86
    private AbstractField<String> specificEpithetField;
87

    
88
    private AbstractField<String> infraSpecificEpithetField;
89

    
90
    private SwitchableTextField fullTitleCacheFiled;
91

    
92
    private SwitchableTextField protectedNameCacheField;
93

    
94
    private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
95

    
96
    private TextField nomenclaturalReferenceDetail;
97

    
98
    private TeamOrPersonField exBasionymAuthorshipField;
99

    
100
    private TeamOrPersonField basionymAuthorshipField;
101

    
102
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
103

    
104
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> replacedSynonymsComboboxSelect;
105

    
106
    private NameRelationField validationField;
107

    
108
    private CheckBox basionymToggle;
109

    
110
    private CheckBox replacedSynonymsToggle;
111

    
112
    private CheckBox validationToggle;
113

    
114
    private ListSelect rankSelect;
115

    
116
    private TeamOrPersonField combinationAuthorshipField;
117

    
118
    private TeamOrPersonField exCombinationAuthorshipField;
119

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

    
122
    private Boolean isInferredCombinationAuthorship = null;
123

    
124
    private Boolean isInferredBasionymAuthorship = null;
125

    
126
    private Boolean isInferredExBasionymAuthorship = null;
127

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

    
130
    private Boolean isInferredExCombinationAuthorship;
131

    
132
    private int specificEpithetFieldRow;
133

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

    
136
    private FilterableAnnotationsField annotationsListField;
137

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

    
140
    private int genusOrUninomialRow;
141

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

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

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

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

    
179

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

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

    
195
    }
196

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

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

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

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

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

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

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

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

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

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

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

    
259
         ** ViralName attributes **
260
         - acronym
261

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

    
271
        int row = 0;
272

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

    
280
        basionymToggle = new CheckBox("With basionym");
281
        basionymToggle.setValue(HAS_BASIONYM_DEFAULT);
282

    
283
        basionymToggle.setStyleName(getDefaultComponentStyles());
284
        grid.addComponent(basionymToggle, 2, row, 3, row);
285
        grid.setComponentAlignment(basionymToggle, Alignment.BOTTOM_LEFT);
286

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

    
292
        row++;
293
        validationToggle = new CheckBox("Validation");
294

    
295
        grid.addComponent(validationToggle, 2, row, 3, row);
296
        grid.setComponentAlignment(validationToggle, Alignment.BOTTOM_LEFT);
297

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

    
318
        row++;
319
        grid.addComponent(new Label("Hint: <i>Edit nomenclatural authors in the nomenclatural reference.</i>", ContentMode.HTML), 0, row, 3, row);
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.addClickListenerAddEntity(e -> getViewEventBus().publish(
329
                this,
330
                new ReferenceEditorAction(EditorActionType.ADD, null, nomReferenceCombobox, this)
331
                ));
332
        nomReferenceCombobox.addClickListenerEditEntity(e -> {
333
            if(nomReferenceCombobox.getValue() != null){
334
                getViewEventBus().publish(this,
335
                    new ReferenceEditorAction(
336
                            EditorActionType.EDIT,
337
                            nomReferenceCombobox.getValue().getUuid(),
338
                            e.getButton(),
339
                            nomReferenceCombobox,
340
                            this)
341
                );
342
            }
343
            });
344

    
345

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

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

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

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

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

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

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

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

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

    
406
        // --------------- Validation
407
        row++;
408
        validationField = new NameRelationField("Validation", Direction.relatedTo, NameRelationshipType.VALIDATED_BY_NAME());
409
        validationField.setWidth(100, Unit.PERCENTAGE);
410
        ToOneRelatedEntityCombobox<TaxonName> validatedNameComboBox = validationField.getValidatedNameComboBox();
411
        validatedNameComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
412
                this,
413
                new TaxonNameEditorAction(EditorActionType.ADD, null, validatedNameComboBox, this)
414
                ));
415
        validatedNameComboBox.addClickListenerEditEntity(e -> {
416
            if(validatedNameComboBox.getValue() != null){
417
                getViewEventBus().publish(this,
418
                    new TaxonNameEditorAction(
419
                            EditorActionType.EDIT,
420
                            validatedNameComboBox.getValue().getUuid(),
421
                            e.getButton(),
422
                            validatedNameComboBox,
423
                            this)
424
                );
425
            }
426
        });
427
        ToOneRelatedEntityCombobox<Reference> validationCitatonComboBox = validationField.getCitatonComboBox();
428
        validationCitatonComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
429
                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
        row++;
448
        exCombinationAuthorshipField = new TeamOrPersonField("Ex-combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
449
        exCombinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
450
        addField(exCombinationAuthorshipField, "exCombinationAuthorship", 0, row, GRID_COLS-1, row);
451

    
452
        row++;
453
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
454
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
455
        annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
456
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
457

    
458
        // -----------------------------------------------------------------------------
459

    
460
        setAdvancedModeEnabled(true);
461
        registerAdvancedModeComponents(fullTitleCacheFiled, protectedNameCacheField);
462

    
463
        registerAdvancedModeComponents(combinationAuthorshipField);
464
        registerAdvancedModeComponents(basionymAuthorshipField);
465
        registerAdvancedModeComponents(exBasionymAuthorshipField);
466
        registerAdvancedModeComponents(exCombinationAuthorshipField);
467

    
468
        registerAdvancedModeComponents(combinationAuthorshipField.getCachFields());
469
        registerAdvancedModeComponents(exCombinationAuthorshipField.getCachFields());
470
        registerAdvancedModeComponents(basionymAuthorshipField.getCachFields());
471
        registerAdvancedModeComponents(exBasionymAuthorshipField.getCachFields());
472

    
473
        setAdvancedMode(false);
474

    
475
    }
476

    
477
    protected TeamOrPersonBase inferBasiomynAuthors() {
478
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
479
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
480
            TaxonName basionym = basionyms.get(0);
481
            if(basionym.getCombinationAuthorship() != null){
482
                return basionym.getCombinationAuthorship();
483
            } else if(basionym.getNomenclaturalReference() != null){
484
                return basionym.getNomenclaturalReference().getAuthorship();
485
            }
486
        }
487
        return null;
488
    }
489

    
490
    protected TeamOrPersonBase inferExBasiomynAuthors() {
491
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
492
        if(!basionyms.isEmpty() && basionyms.get(0) != null){
493
            TaxonName basionym = basionyms.get(0);
494
                return basionym.getExCombinationAuthorship();
495
        }
496
        return null;
497
    }
498

    
499
    protected TeamOrPersonBase inferCombinationAuthors() {
500
        Reference nomRef = nomReferenceCombobox.getValue();
501
        if(nomRef != null) {
502
            return nomRef.getAuthorship();
503
        }
504
        return null;
505
    }
506

    
507
    protected TeamOrPersonBase inferExCombinationAuthors() {
508
        NameRelationshipDTO nameRelationDTO = validationField.getValue();
509
        if(nameRelationDTO != null && nameRelationDTO.getOtherName() != null){
510
            TaxonName validatedName = nameRelationDTO.getOtherName();
511
            if(validatedName.getCombinationAuthorship() != null) {
512
                return validatedName.getCombinationAuthorship();
513
            } else if(validatedName.getNomenclaturalReference() != null){
514
                return validatedName.getNomenclaturalReference().getAuthorship();
515
            }
516
        }
517
        return null;
518
    }
519

    
520
    @Override
521
    protected void afterItemDataSourceSet() {
522

    
523

    
524
        rankSelect.addValueChangeListener(updateFieldVisibilityListener);
525
        basionymToggle.addValueChangeListener(e -> {
526
            updateAuthorshipFields();
527
        });
528
        validationToggle.addValueChangeListener(e -> {
529
            updateAuthorshipFields();
530
            });
531
        replacedSynonymsToggle.addValueChangeListener(e -> {
532
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
533
            replacedSynonymsComboboxSelect.setVisible(enable);
534
        });
535

    
536

    
537
        TaxonNameDTO taxonNameDTO = getBean();
538
        boolean showBasionymSection = taxonNameDTO.getBasionyms().size() > 0
539
                || taxonNameDTO.getBasionymAuthorship() != null
540
                || taxonNameDTO.getExBasionymAuthorship() != null;
541
        basionymToggle.setValue(showBasionymSection);
542
        basionymToggle.setReadOnly(showBasionymSection);
543

    
544
        boolean showReplacedSynonyms = taxonNameDTO.getReplacedSynonyms().size() > 0;
545
        replacedSynonymsToggle.setValue(showReplacedSynonyms);
546
        replacedSynonymsToggle.setReadOnly(showReplacedSynonyms);
547
        replacedSynonymsComboboxSelect.setVisible(showReplacedSynonyms);
548

    
549
        boolean showValidationSection = taxonNameDTO.getValidationFor() != null || taxonNameDTO.getExCombinationAuthorship() != null;
550

    
551
        validationToggle.setValue(showValidationSection);
552
        validationToggle.setReadOnly(showValidationSection);
553
//        validationField.setVisible(showValidation);
554
//        exCombinationAuthorshipField.setVisible(showExAuthors);
555

    
556
        if(isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
557
            updateAuthorshipFields();
558
        }
559
        if(isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY) && getBean().getNomenclaturalReference() != null) {
560
            nomReferenceCombobox.setCaption("Selection limited to nomenclatural reference and sections");
561
        }
562
        if(isModeEnabled(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE)) {
563
            if(combinationAuthorshipField.getValue() == null){
564
                nomReferenceCombobox.setRequired(true);
565
            } else {
566
                combinationAuthorshipField.addValueChangeListener(e -> {
567
                    if(e.getProperty().getValue() == null){
568
                        nomReferenceCombobox.setRequired(true);
569
                    }
570
                });
571
            }
572
        }
573

    
574
    }
575

    
576
    /**
577
     * Updates all authorship fields if the an authorship field is empty this method attempts to infer the
578
     * authors from the related nomenclatural reference or taxon name.
579
     * <p>
580
     * Finally the {@link #updateFieldVisibility()} is invoked.
581
     *
582
     * @param taxonName
583
     */
584
    @Override
585
    public void updateAuthorshipFields() {
586

    
587
        TaxonNameDTO taxonName = getBean();
588

    
589
        // ------------- CombinationAuthors
590
        isInferredCombinationAuthorship = updateAuthorshipFieldData(
591
                taxonName.getCombinationAuthorship(),
592
                inferCombinationAuthors(),
593
                combinationAuthorshipField,
594
                nomReferenceCombobox.getSelect(),
595
                isInferredCombinationAuthorship);
596

    
597

    
598
        // ------------- Basionym and ExBasionymAuthors
599
        if(BooleanUtils.isTrue(basionymToggle.getValue())){
600

    
601
            isInferredBasionymAuthorship = updateAuthorshipFieldData(
602
                    taxonName.getBasionymAuthorship(),
603
                    inferBasiomynAuthors(),
604
                    basionymAuthorshipField,
605
                    basionymsComboboxSelect,
606
                    isInferredBasionymAuthorship
607
                    );
608

    
609
            isInferredExBasionymAuthorship = updateAuthorshipFieldData(
610
                    taxonName.getExBasionymAuthorship(),
611
                    inferExBasiomynAuthors(),
612
                    exBasionymAuthorshipField,
613
                    basionymsComboboxSelect,
614
                    isInferredExBasionymAuthorship
615
                    );
616

    
617
        }
618

    
619
        // ------------- Validation and ExCombinationAuthors
620
        isInferredExCombinationAuthorship = updateAuthorshipFieldData(
621
                taxonName.getExCombinationAuthorship(),
622
                inferExCombinationAuthors(),
623
                exCombinationAuthorshipField,
624
                validationField.getValidatedNameComboBox(),
625
                isInferredExCombinationAuthorship
626
                );
627

    
628
        updateFieldVisibility();
629

    
630
    }
631

    
632
//    /**
633
//     *
634
//     */
635
//    protected void updateAuthorshipFieldsVisibility() {
636
//        combinationAuthorshipField.setVisible(!isInferredCombinationAuthorship);
637
//        if(BooleanUtils.isTrue(basionymToggle.getValue())){
638
//            basionymAuthorshipField.setVisible(!isInferredBasionymAuthorship);
639
//            exBasionymAuthorshipField.setVisible(!isInferredExBasionymAuthorship);
640
//        }
641
//    }
642

    
643
    /**
644
     *
645
     * @param authorship
646
     *    the value of the taxonName authorship field
647
     * @param inferredAuthors
648
     *    the value inferred from other fields which may be set as authorship to the taxon name
649
     * @param authorshipField
650
     *    the ui element to edit the taxonName authorship field
651
     * @param updateTriggerField
652
     * @param lastInferredAuthorshipState
653
     * @return
654
     */
655
    protected Boolean updateAuthorshipFieldData(TeamOrPersonBase<?> authorship, TeamOrPersonBase inferredAuthors,
656
            TeamOrPersonField authorshipField, AbstractField updateTriggerField,
657
            Boolean lastInferredAuthorshipState) {
658

    
659
        if(authorship == null){
660
            authorshipField.setValue(inferredAuthors);
661
            lastInferredAuthorshipState = true;
662
        } else {
663
            boolean authorshipMatch = authorship == inferredAuthors;
664
            if(lastInferredAuthorshipState == null){
665
                // initialization of authorshipState, this comes only into account when the editor is just being initialized
666
                lastInferredAuthorshipState = authorshipMatch;
667
            }
668
            if(!authorshipMatch && lastInferredAuthorshipState){
669
                // update the combinationAuthorshipField to follow changes of the nomenclatural reference in case it was autofilled before
670
                authorshipField.setValue(inferredAuthors);
671
                lastInferredAuthorshipState = true;
672
            }
673
        }
674

    
675
        if(updateTriggerField != null){
676
            // IMPORTANT!
677
            // this ChangeListener must be added at this very late point in the editor lifecycle so that it is called after
678
            // the ToOneRelatedEntityReloader which may have been added to the updateTriggerField in the presenters handleViewEntered() method.
679
            // Otherwise we risk multiple representation problems in the hibernate session
680
            if(!authorshipUpdateListeners.containsKey(updateTriggerField)){
681
                ValueChangeListener listener = e ->  {
682
                    logger.debug(" value changed #2");
683
                    updateAuthorshipFields();
684
                };
685
                updateTriggerField.addValueChangeListener(listener);
686
                authorshipUpdateListeners.put(updateTriggerField, listener);
687
            }
688
        }
689

    
690
        return lastInferredAuthorshipState;
691
    }
692

    
693
    /**
694
     * @param rank
695
     * @return
696
     */
697
    private void updateFieldVisibility() {
698

    
699
        // TODO use getField() instead and remove field references
700
        Rank rank = (Rank) rankSelect.getValue();
701

    
702
        boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES());
703
        Boolean withBasionymSection = BooleanUtils.isTrue(basionymToggle.getValue());
704
        Boolean withValidationSection = BooleanUtils.isTrue(validationToggle.getValue());
705

    
706
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
707
            if(isSpeciesOrBelow) {
708
                if(TextField.class.isAssignableFrom(genusOrUninomialField.getClass())){
709
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
710
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
711
                            this,
712
                            new TaxonNameEditorActionStrRep(EditorActionType.ADD, e.getButton(), combobox, this)
713
                        ));
714
                    combobox.addClickListenerEditEntity(e -> {
715
                        if(combobox.getValue() != null){
716
                            getViewEventBus().publish(this,
717
                                new TaxonNameEditorActionStrRep(
718
                                        EditorActionType.EDIT,
719
                                        combobox.getIdForValue(),
720
                                        e.getButton(),
721
                                        combobox,
722
                                        this)
723
                            );
724
                        }
725
                    });
726
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, combobox, 0, genusOrUninomialRow, 1, genusOrUninomialRow);
727
                }
728
            } else {
729
                if(ToOneRelatedEntityCombobox.class.isAssignableFrom(genusOrUninomialField.getClass())) {
730
                    genusOrUninomialField = replaceComponent("genusOrUninomial", genusOrUninomialField, new TextFieldNFix(), 0, genusOrUninomialRow, 1, genusOrUninomialRow);
731
                }
732
            }
733
        }
734

    
735
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
736
            if(rank.isInfraSpecific()) {
737
                if(TextField.class.isAssignableFrom(specificEpithetField.getClass())) {
738
                    WeaklyRelatedEntityCombobox<TaxonName> combobox = new WeaklyRelatedEntityCombobox<TaxonName>("-> this caption will be replaced <-", TaxonName.class);
739
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, combobox, 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
740
                    combobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
741
                            this,
742
                            new TaxonNameEditorActionStrRep(EditorActionType.ADD, e.getButton(), combobox, this)
743
                        ));
744
                    combobox.addClickListenerEditEntity(e -> {
745
                        if(combobox.getValue() != null){
746
                            getViewEventBus().publish(this,
747
                                new TaxonNameEditorActionStrRep(
748
                                        EditorActionType.EDIT,
749
                                        combobox.getIdForValue(),
750
                                        e.getButton(),
751
                                        combobox,
752
                                        this)
753
                            );
754
                        }
755
                    });
756
                }
757
            } else {
758
                if(ToOneRelatedEntityCombobox.class.isAssignableFrom(specificEpithetField.getClass())) {
759
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, new TextFieldNFix(), 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
760
               }
761
            }
762
        }
763

    
764
        specificEpithetField.setVisible(isSpeciesOrBelow);
765
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
766
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
767

    
768
        basionymsComboboxSelect.setVisible(withBasionymSection);
769

    
770
        combinationAuthorshipField.setVisible(isInferredCombinationAuthorship != null && !isInferredCombinationAuthorship);
771
        basionymAuthorshipField.setVisible(withBasionymSection && isInferredBasionymAuthorship != null && !isInferredBasionymAuthorship);
772
        exBasionymAuthorshipField.setVisible(withBasionymSection && isInferredExBasionymAuthorship != null && !isInferredExBasionymAuthorship);
773

    
774
        validationField.setVisible(withValidationSection);
775
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
776

    
777

    
778
//        if(taxonName != null){
779
//            if(modesActive.contains(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
780
//            }
781
//        }
782

    
783
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
784
        specificEpithetField.setVisible(isSpeciesOrBelow);
785
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
786
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
787
    }
788

    
789

    
790
    @Override
791
    public void cancel() {
792
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
793
        rankSelect.removeValueChangeListener(updateFieldVisibilityListener);
794
        super.cancel();
795
    }
796

    
797
    /**
798
     * {@inheritDoc}
799
     */
800
    @Override
801
    public boolean allowAnonymousAccess() {
802
        return false;
803
    }
804

    
805
    /**
806
     * {@inheritDoc}
807
     */
808
    @Override
809
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
810
        return null;
811
    }
812

    
813
    /**
814
     * {@inheritDoc}
815
     */
816
    @Override
817
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
818
        return nomReferenceCombobox;
819
    }
820

    
821
    /**
822
     * {@inheritDoc}
823
     */
824
    @Override
825
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
826
        return basionymsComboboxSelect;
827
    }
828

    
829
    /**
830
     * {@inheritDoc}
831
     */
832
    @Override
833
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
834
        return replacedSynonymsComboboxSelect;
835
    }
836

    
837
    /**
838
     * {@inheritDoc}
839
     */
840
    @Override
841
    public ListSelect getRankSelect() {
842
        return rankSelect;
843
    }
844

    
845
    /**
846
     * {@inheritDoc}
847
     */
848
    @Override
849
    public AbstractField<String> getGenusOrUninomialField(){
850
        return genusOrUninomialField;
851
    }
852

    
853
    /**
854
     * @return the exBasionymAuthorshipField
855
     */
856
    @Override
857
    public TeamOrPersonField getExBasionymAuthorshipField() {
858
        return exBasionymAuthorshipField;
859
    }
860

    
861
    /**
862
     * @return the basionymAuthorshipField
863
     */
864
    @Override
865
    public TeamOrPersonField getBasionymAuthorshipField() {
866
        return basionymAuthorshipField;
867
    }
868

    
869
    /**
870
     * @return the combinationAuthorshipField
871
     */
872
    @Override
873
    public TeamOrPersonField getCombinationAuthorshipField() {
874
        return combinationAuthorshipField;
875
    }
876

    
877
    /**
878
     * @return the exCombinationAuthorshipField
879
     */
880
    @Override
881
    public TeamOrPersonField getExCombinationAuthorshipField() {
882
        return exCombinationAuthorshipField;
883
    }
884

    
885
    @Override
886
    public NameRelationField getValidationField(){
887
        return validationField;
888
    }
889

    
890
    @Override
891
    public void enableMode(TaxonNamePopupEditorMode mode){
892
            modesActive.add(mode);
893
    }
894

    
895
    @Override
896
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
897
        return modesActive.contains(mode);
898
    }
899

    
900
    @Override
901
    public void disableMode(TaxonNamePopupEditorMode mode){
902
        modesActive.remove(mode);
903
    }
904

    
905
    @Override
906
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
907
        return modesActive;
908
    }
909

    
910
    @Override
911
    public CheckBox getBasionymToggle() {
912
        return basionymToggle;
913
    }
914

    
915
    @Override
916
    public FilterableAnnotationsField getAnnotationsField() {
917
        return annotationsListField;
918
    }
919

    
920
    /**
921
     * {@inheritDoc}
922
     */
923
    @Override
924
    public void setReadOnly(boolean readOnly) {
925
        boolean basionymToggleReadonly = basionymToggle.isReadOnly();
926
        boolean validationToggleReadonly = validationToggle.isReadOnly();
927
        super.setReadOnly(readOnly);
928
        combinationAuthorshipField.setEditorReadOnly(readOnly);
929
        exCombinationAuthorshipField.setEditorReadOnly(readOnly);
930
        basionymAuthorshipField.setEditorReadOnly(readOnly);
931
        exBasionymAuthorshipField.setEditorReadOnly(readOnly);
932
        // preserve old readonly states if they were true
933
        if(basionymToggleReadonly){
934
            basionymToggle.setReadOnly(true);
935
        }
936
        if(validationToggleReadonly){
937
            validationToggle.setReadOnly(true);
938
        }
939
    }
940

    
941

    
942

    
943
    /**
944
     * @return the infraGenericEpithetField
945
     */
946
    @Override
947
    public AbstractField<String> getInfraGenericEpithetField() {
948
        return infraGenericEpithetField;
949
    }
950

    
951
    /**
952
     * @return the specificEpithetField
953
     */
954
    @Override
955
    public AbstractField<String> getSpecificEpithetField() {
956
        return specificEpithetField;
957
    }
958

    
959
    /**
960
     * @return the infraSpecificEpithetField
961
     */
962
    @Override
963
    public AbstractField<String> getInfraSpecificEpithetField() {
964
        return infraSpecificEpithetField;
965
    }
966

    
967

    
968
}
(10-10/13)