Project

General

Profile

Download (33.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.apache.log4j.Level;
20
import org.springframework.context.annotation.Scope;
21
import org.springframework.security.core.GrantedAuthority;
22
import org.vaadin.viritin.fields.LazyComboBox;
23

    
24
import com.vaadin.data.Property;
25
import com.vaadin.data.Property.ValueChangeListener;
26
import com.vaadin.shared.ui.label.ContentMode;
27
import com.vaadin.spring.annotation.SpringComponent;
28
import com.vaadin.ui.AbstractField;
29
import com.vaadin.ui.Alignment;
30
import com.vaadin.ui.CheckBox;
31
import com.vaadin.ui.GridLayout;
32
import com.vaadin.ui.Label;
33
import com.vaadin.ui.ListSelect;
34
import com.vaadin.ui.TextField;
35

    
36
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
37
import eu.etaxonomy.cdm.model.common.CdmBase;
38
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
39
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
40
import eu.etaxonomy.cdm.model.name.Rank;
41
import eu.etaxonomy.cdm.model.name.TaxonName;
42
import eu.etaxonomy.cdm.model.reference.Reference;
43
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
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.model.name.NameRelationshipDTO;
48
import eu.etaxonomy.cdm.vaadin.model.name.TaxonNameDTO;
49
import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
50
import eu.etaxonomy.cdm.vaadin.permission.CdmEditDeletePermissionTester;
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.event.EditorActionType;
59
import eu.etaxonomy.vaadin.mvp.AbstractCdmDTOPopupEditor;
60

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

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

    
72
    private final static int GRID_COLS = 4;
73

    
74
    private final static int GRID_ROWS = 16;
75

    
76
    private static final boolean HAS_BASIONYM_DEFAULT = false;
77

    
78
    private AbstractField<String> genusOrUninomialField;
79

    
80
    private AbstractField<String> infraGenericEpithetField;
81

    
82
    private AbstractField<String> specificEpithetField;
83

    
84
    private AbstractField<String> infraSpecificEpithetField;
85

    
86
    private SwitchableTextField fullTitleCacheFiled;
87

    
88
    private SwitchableTextField protectedNameCacheField;
89

    
90
    private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
91

    
92
    private TextField nomenclaturalReferenceDetail;
93

    
94
    private TeamOrPersonField exBasionymAuthorshipField;
95

    
96
    private TeamOrPersonField basionymAuthorshipField;
97

    
98
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
99

    
100
    private ToManyRelatedEntitiesComboboxSelect<TaxonName> replacedSynonymsComboboxSelect;
101

    
102
    private NameRelationField validationField;
103

    
104
    private CheckBox basionymToggle;
105

    
106
    private CheckBox replacedSynonymsToggle;
107

    
108
    private CheckBox validationToggle;
109

    
110
    private ListSelect rankSelect;
111

    
112
    private TeamOrPersonField combinationAuthorshipField;
113

    
114
    private TeamOrPersonField exCombinationAuthorshipField;
115

    
116
    private EnumSet<TaxonNamePopupEditorMode> modesActive = EnumSet.noneOf(TaxonNamePopupEditorMode.class);
117

    
118
    private Boolean isInferredCombinationAuthorship = null;
119

    
120
    private Boolean isInferredBasionymAuthorship = null;
121

    
122
    private Boolean isInferredExBasionymAuthorship = null;
123

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

    
126
    private Boolean isInferredExCombinationAuthorship;
127

    
128
    private int specificEpithetFieldRow;
129

    
130
    /**
131
     * @param layout
132
     * @param dtoType
133
     */
134
    public TaxonNamePopupEditor() {
135
        super(new GridLayout(GRID_COLS, GRID_ROWS), TaxonNameDTO.class);
136
    }
137

    
138
    /**
139
     * {@inheritDoc}
140
     */
141
    @Override
142
    public String getWindowCaption() {
143
        return "Name editor";
144
    }
145

    
146

    
147

    
148
    /**
149
     * {@inheritDoc}
150
     */
151
    @Override
152
    public int getWindowWidth() {
153
        return 800;
154
    }
155

    
156
    /**
157
     * {@inheritDoc}
158
     */
159
    @Override
160
    public void focusFirst() {
161
        // titleField.focus();
162

    
163
    }
164

    
165
    /**
166
     * {@inheritDoc}
167
     */
168
    @Override
169
    protected String getDefaultComponentStyles() {
170
        return "tiny";
171
    }
172

    
173
    /**
174
     * {@inheritDoc}
175
     */
176
    @Override
177
    protected void initContent() {
178

    
179
        GridLayout grid = (GridLayout)getFieldLayout();
180
        grid.setSizeFull();
181
        grid.setHideEmptyRowsAndColumns(true);
182
        grid.setSpacing(true);
183
        grid.setColumnExpandRatio(0, 0.3f);
184
        grid.setColumnExpandRatio(1, 0.3f);
185
        grid.setColumnExpandRatio(2, 0.3f);
186
        grid.setColumnExpandRatio(3, 0.0f);
187

    
188
        /*
189
         - nameType: preset, needs to be set in the presenter for new names
190
         - appendedPhrase: -> TODO field
191
         - nomenclaturalMicroReference:  -> TODO field
192
         - nomenclaturalReference ->  field but disabled for REGISTRY
193
         - rank -> SelectField which determines the visiblity of the other fields
194

    
195
         - fullTitleCache + protectedFullTitleCache -> SwitchableTextField : ADVANCED_MODE
196
         - nameCache + protectedNameCache -> SwitchableTextField : ADVANCED_MODE
197

    
198
         - homotypicalGroup -> hidden
199
         - typeDesignations -> hidden
200
         - descriptions -> hidden
201
         - taxonBases -> hidden
202
         - registrations -> hidden
203

    
204
         - relationsFromThisName-> TODO implement later
205
         - relationsToThisName -> TODO implement later
206

    
207
         - genusOrUninomial -> textField
208
         - infraGenericEpithet  -> textField
209
         - specificEpithet  -> textField
210
         - infraSpecificEpithet  -> textField
211

    
212
         - authorshipCache + protectedAuthorshipCache -> SwitchableTextField : only ADVANCED_MODE and disabled for REGISTRY
213
         - basionymAuthorship -> field but disabled for REGISTRY, basionym is set as nameRelationShip
214
         - combinationAuthorship -> field but disabled for REGISTRY author team of the reference
215
         - exCombinationAuthorship -> textField
216
         - exBasionymAuthorship -> textField
217

    
218
         - status -> TODO field
219
         - monomHybrid -> TODO implement hybrids later
220
         - binomHybrid -> TODO implement hybrids later
221
         - trinomHybrid -> TODO implement hybrids later
222

    
223
         - hybridParentRelations -> TODO implement hybrids later
224
         - hybridChildRelations -> TODO implement hybrids later
225
         - hybridFormula -> TODO implement hybrids later
226

    
227
         ** ViralName attributes **
228
         - acronym
229

    
230
         ** BacterialName attributes **
231
         - subGenusAuthorship
232
         - nameApprobation
233
         - breed
234
         - publicationYear
235
         - originalPublicationYear
236
         - cultivarName
237
        */
238

    
239
        int row = 0;
240

    
241
        rankSelect = new ListSelect("Rank");
242
        rankSelect.setNullSelectionAllowed(false);
243
        rankSelect.setRows(1);
244
        rankSelect.setWidth(100, Unit.PERCENTAGE);
245
        addField(rankSelect, "rank", 0, row, 1, row);
246
        grid.setComponentAlignment(rankSelect, Alignment.TOP_RIGHT);
247

    
248
        basionymToggle = new CheckBox("With basionym");
249
        basionymToggle.setValue(HAS_BASIONYM_DEFAULT);
250

    
251
        basionymToggle.setStyleName(getDefaultComponentStyles());
252
        grid.addComponent(basionymToggle, 2, row, 3, row);
253
        grid.setComponentAlignment(basionymToggle, Alignment.BOTTOM_LEFT);
254

    
255
        row++;
256
        replacedSynonymsToggle = new CheckBox("With replaced synonym");
257
        grid.addComponent(replacedSynonymsToggle, 2, row, 3, row);
258
        grid.setComponentAlignment(replacedSynonymsToggle, Alignment.BOTTOM_LEFT);
259

    
260
        row++;
261
        validationToggle = new CheckBox("Validation");
262

    
263
        grid.addComponent(validationToggle, 2, row, 3, row);
264
        grid.setComponentAlignment(validationToggle, Alignment.BOTTOM_LEFT);
265

    
266
        row++;
267
        // fullTitleCache
268
        fullTitleCacheFiled = addSwitchableTextField("Full title cache", "fullTitleCache", "protectedFullTitleCache", 0, row, GRID_COLS-1, row);
269
        fullTitleCacheFiled.setWidth(100, Unit.PERCENTAGE);
270
        row++;
271
        protectedNameCacheField = addSwitchableTextField("Name cache", "nameCache", "protectedNameCache", 0, row, GRID_COLS-1, row);
272
        protectedNameCacheField.setWidth(100, Unit.PERCENTAGE);
273
        row++;
274
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
275
            genusOrUninomialField = addTextField("Genus or uninomial", "genusOrUninomial", 0, row, 1, row);
276
        } else {
277
            genusOrUninomialField = new LazyComboBox<String>(String.class);
278
            addField(genusOrUninomialField, "genusOrUninomial", 0, row, 1, row);
279
        }
280
        genusOrUninomialField.setWidth(200, Unit.PIXELS);
281
        infraGenericEpithetField = addTextField("Infrageneric epithet", "infraGenericEpithet", 2, row, 3, row);
282
        infraGenericEpithetField.setWidth(200, Unit.PIXELS);
283
        row++;
284
        specificEpithetFieldRow = row;
285
        specificEpithetField = addTextField("Specific epithet", "specificEpithet", 0, row, 1, row);
286
        specificEpithetField.setWidth(200, Unit.PIXELS);
287
        infraSpecificEpithetField = addTextField("Infraspecific epithet", "infraSpecificEpithet", 2, row, 3, row);
288
        infraSpecificEpithetField.setWidth(200, Unit.PIXELS);
289

    
290
        row++;
291
        grid.addComponent(new Label("Hint: <i>Edit nomenclatural authors in the nomenclatural reference.</i>", ContentMode.HTML), 0, row, 3, row);
292

    
293
        row++;
294
        combinationAuthorshipField = new TeamOrPersonField("Combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
295
        combinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
296
        addField(combinationAuthorshipField, "combinationAuthorship", 0, row, GRID_COLS-1, row);
297

    
298
        row++;
299
        nomReferenceCombobox = new ToOneRelatedEntityCombobox<Reference>("Nomenclatural reference", Reference.class);
300
        nomReferenceCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(
301
                this,
302
                new ReferenceEditorAction(EditorActionType.ADD, null, nomReferenceCombobox, this)
303
                ));
304
        nomReferenceCombobox.addClickListenerEditEntity(e -> {
305
            if(nomReferenceCombobox.getValue() != null){
306
                getViewEventBus().publish(this,
307
                    new ReferenceEditorAction(
308
                            EditorActionType.EDIT,
309
                            nomReferenceCombobox.getValue().getUuid(),
310
                            e.getButton(),
311
                            nomReferenceCombobox,
312
                            this)
313
                );
314
            }
315
            });
316
        logger.setLevel(Level.DEBUG);
317
        // nomReferenceCombobox.getSelect().addValueChangeListener(e -> logger.debug("nomReferenceCombobox value changed #1"));
318
        // nomReferenceCombobox.setWidth(300, Unit.PIXELS);
319
        nomReferenceCombobox.setWidth("100%");
320
        addField(nomReferenceCombobox, "nomenclaturalReference", 0, row, 2, row);
321
        nomenclaturalReferenceDetail = addTextField("Reference detail", "nomenclaturalMicroReference", 3, row, 3, row);
322
        nomenclaturalReferenceDetail.setWidth(100, Unit.PIXELS);
323

    
324
        // --------------- Basionyms
325
        row++;
326
        basionymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Basionym");
327
        basionymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
328
        addField(basionymsComboboxSelect, "basionyms", 0, row, 3, row);
329
        basionymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
330
        basionymsComboboxSelect.withEditButton(true);
331
        basionymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
332
        basionymsComboboxSelect.setEditActionListener(e -> {
333

    
334
            Object fieldValue = e.getSource().getValue();
335
            UUID beanUuid = null;
336
            if(fieldValue != null){
337
                beanUuid = ((CdmBase)fieldValue).getUuid();
338

    
339
            }
340
            ReloadableLazyComboBox<TaxonName>  lazyCombobox = (ReloadableLazyComboBox<TaxonName>) e.getSource();
341
            getViewEventBus().publish(this, new TaxonNameEditorAction(e.getAction(), beanUuid, null, lazyCombobox, this));
342
        });
343
        grid.setComponentAlignment(basionymsComboboxSelect, Alignment.TOP_RIGHT);
344

    
345
        row++;
346
        basionymAuthorshipField = new TeamOrPersonField("Basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
347
        basionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
348
        addField(basionymAuthorshipField, "basionymAuthorship", 0, row, GRID_COLS-1, row);
349
        row++;
350
        exBasionymAuthorshipField = new TeamOrPersonField("Ex-basionym author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
351
        exBasionymAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
352
        addField(exBasionymAuthorshipField, "exBasionymAuthorship", 0, row, GRID_COLS-1, row);
353

    
354
        // --------------- ReplacedSynonyms
355
        row++;
356
        replacedSynonymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Replaced synonyms");
357
        replacedSynonymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
358
        addField(replacedSynonymsComboboxSelect, "replacedSynonyms", 0, row, 3, row);
359
        replacedSynonymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
360
        replacedSynonymsComboboxSelect.withEditButton(true);
361
        replacedSynonymsComboboxSelect.setEditPermissionTester(new CdmEditDeletePermissionTester());
362
        replacedSynonymsComboboxSelect.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(replacedSynonymsComboboxSelect, Alignment.TOP_RIGHT);
374

    
375
        // --------------- Validation
376
        row++;
377
        validationField = new NameRelationField("Validation", Direction.relatedTo, NameRelationshipType.VALIDATED_BY_NAME());
378
        validationField.setWidth(100, Unit.PERCENTAGE);
379
        ToOneRelatedEntityCombobox<TaxonName> validatedNameComboBox = validationField.getValidatedNameComboBox();
380
        validatedNameComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
381
                this,
382
                new TaxonNameEditorAction(EditorActionType.ADD, null, validatedNameComboBox, this)
383
                ));
384
        validatedNameComboBox.addClickListenerEditEntity(e -> {
385
            if(validatedNameComboBox.getValue() != null){
386
                getViewEventBus().publish(this,
387
                    new TaxonNameEditorAction(
388
                            EditorActionType.EDIT,
389
                            validatedNameComboBox.getValue().getUuid(),
390
                            e.getButton(),
391
                            validatedNameComboBox,
392
                            this)
393
                );
394
            }
395
        });
396
        ToOneRelatedEntityCombobox<Reference> validationCitatonComboBox = validationField.getCitatonComboBox();
397
        validationCitatonComboBox.addClickListenerAddEntity(e -> getViewEventBus().publish(
398
                this,
399
                new ReferenceEditorAction(EditorActionType.ADD, null, validationCitatonComboBox, this)
400
                ));
401
        validationCitatonComboBox.addClickListenerEditEntity(e -> {
402
            if(validationCitatonComboBox.getValue() != null){
403
                getViewEventBus().publish(this,
404
                    new ReferenceEditorAction(
405
                            EditorActionType.EDIT,
406
                            validationCitatonComboBox.getValue().getUuid(),
407
                            e.getButton(),
408
                            validationCitatonComboBox,
409
                            this)
410
                );
411
            }
412
        });
413
        addField(validationField, "validationFor", 0, row, 3, row);
414
        grid.setComponentAlignment(validationField, Alignment.TOP_RIGHT);
415

    
416
        row++;
417
        exCombinationAuthorshipField = new TeamOrPersonField("Ex-combination author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
418
        exCombinationAuthorshipField.setWidth(100,  Unit.PERCENTAGE);
419
        addField(exCombinationAuthorshipField, "exCombinationAuthorship", 0, row, GRID_COLS-1, row);
420

    
421
        // -----------------------------------------------------------------------------
422

    
423
        setAdvancedModeEnabled(true);
424
        registerAdvancedModeComponents(fullTitleCacheFiled, protectedNameCacheField);
425

    
426
        registerAdvancedModeComponents(combinationAuthorshipField);
427
        registerAdvancedModeComponents(basionymAuthorshipField);
428
        registerAdvancedModeComponents(exBasionymAuthorshipField);
429
        registerAdvancedModeComponents(exCombinationAuthorshipField);
430

    
431
        registerAdvancedModeComponents(combinationAuthorshipField.getCachFields());
432
        registerAdvancedModeComponents(exCombinationAuthorshipField.getCachFields());
433
        registerAdvancedModeComponents(basionymAuthorshipField.getCachFields());
434
        registerAdvancedModeComponents(exBasionymAuthorshipField.getCachFields());
435

    
436
        setAdvancedMode(false);
437

    
438
    }
439

    
440
    protected TeamOrPersonBase inferBasiomynAuthors() {
441
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
442
        if(!basionyms.isEmpty()){
443
            TaxonName basionym = basionyms.get(0);
444
            if(basionym.getCombinationAuthorship() != null){
445
                return basionym.getCombinationAuthorship();
446
            } else if(basionym.getNomenclaturalReference() != null){
447
                return basionym.getNomenclaturalReference().getAuthorship();
448
            }
449
        }
450
        return null;
451
    }
452

    
453
    protected TeamOrPersonBase inferExBasiomynAuthors() {
454
        List<TaxonName> basionyms = basionymsComboboxSelect.getValue();
455
        if(!basionyms.isEmpty()){
456
            TaxonName basionym = basionyms.get(0);
457
                return basionym.getExCombinationAuthorship();
458
        }
459
        return null;
460
    }
461

    
462
    protected TeamOrPersonBase inferCombinationAuthors() {
463
        Reference nomRef = nomReferenceCombobox.getValue();
464
        if(nomRef != null) {
465
            return nomRef.getAuthorship();
466
        }
467
        return null;
468
    }
469

    
470
    protected TeamOrPersonBase inferExCombinationAuthors() {
471
        NameRelationshipDTO nameRelationDTO = validationField.getValue();
472
        if(nameRelationDTO != null && nameRelationDTO.getOtherName() != null){
473
            TaxonName validatedName = nameRelationDTO.getOtherName();
474
            if(validatedName.getCombinationAuthorship() != null) {
475
                return validatedName.getCombinationAuthorship();
476
            } else if(validatedName.getNomenclaturalReference() != null){
477
                return validatedName.getNomenclaturalReference().getAuthorship();
478
            }
479
        }
480
        return null;
481
    }
482

    
483
    @Override
484
    protected void afterItemDataSourceSet() {
485

    
486

    
487
        rankSelect.addValueChangeListener(e -> updateFieldVisibility());
488
        basionymToggle.addValueChangeListener(e -> {
489
            updateAuthorshipFields();
490
        });
491
        validationToggle.addValueChangeListener(e -> {
492
            updateAuthorshipFields();
493
            });
494
        replacedSynonymsToggle.addValueChangeListener(e -> {
495
            boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
496
            replacedSynonymsComboboxSelect.setVisible(enable);
497
        });
498

    
499

    
500
        TaxonNameDTO taxonNameDTO = getBean();
501
        boolean showBasionymSection = taxonNameDTO.getBasionyms().size() > 0
502
                || taxonNameDTO.getBasionymAuthorship() != null
503
                || taxonNameDTO.getExBasionymAuthorship() != null;
504
        basionymToggle.setValue(showBasionymSection);
505
        basionymToggle.setReadOnly(showBasionymSection);
506

    
507
        boolean showReplacedSynonyms = taxonNameDTO.getReplacedSynonyms().size() > 0;
508
        replacedSynonymsToggle.setValue(showReplacedSynonyms);
509
        replacedSynonymsToggle.setReadOnly(showReplacedSynonyms);
510
        replacedSynonymsComboboxSelect.setVisible(showReplacedSynonyms);
511

    
512
        boolean showValidationSection = taxonNameDTO.getValidationFor() != null || taxonNameDTO.getExCombinationAuthorship() != null;
513

    
514
        validationToggle.setValue(showValidationSection);
515
        validationToggle.setReadOnly(showValidationSection);
516
//        validationField.setVisible(showValidation);
517
//        exCombinationAuthorshipField.setVisible(showExAuthors);
518

    
519
        if(isModeEnabled(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
520
            updateAuthorshipFields();
521
        }
522
        if(isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY) && getBean().getNomenclaturalReference() != null) {
523
            nomReferenceCombobox.setCaption("Selection limited to nomenclatural reference and sections");
524
        }
525
        if(isModeEnabled(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE)) {
526
            if(combinationAuthorshipField.getValue() == null){
527
                nomReferenceCombobox.setRequired(true);
528
            } else {
529
                combinationAuthorshipField.addValueChangeListener(e -> {
530
                    if(e.getProperty().getValue() == null){
531
                        nomReferenceCombobox.setRequired(true);
532
                    }
533
                });
534
            }
535
        }
536

    
537
    }
538

    
539
    /**
540
     * Updates all authorship fields if the an authorship field is empty this method attempts to infer the
541
     * authors from the related nomenclatural reference or taxon name.
542
     * <p>
543
     * Finally the {@link #updateFieldVisibility()} is invoked.
544
     *
545
     * @param taxonName
546
     */
547
    @Override
548
    public void updateAuthorshipFields() {
549

    
550
        TaxonNameDTO taxonName = getBean();
551

    
552
        // ------------- CombinationAuthors
553
        isInferredCombinationAuthorship = updateAuthorshipFieldData(
554
                taxonName.getCombinationAuthorship(),
555
                inferCombinationAuthors(),
556
                combinationAuthorshipField,
557
                nomReferenceCombobox.getSelect(),
558
                isInferredCombinationAuthorship);
559

    
560

    
561
        // ------------- Basionym and ExBasionymAuthors
562
        if(BooleanUtils.isTrue(basionymToggle.getValue())){
563

    
564
            isInferredBasionymAuthorship = updateAuthorshipFieldData(
565
                    taxonName.getBasionymAuthorship(),
566
                    inferBasiomynAuthors(),
567
                    basionymAuthorshipField,
568
                    basionymsComboboxSelect,
569
                    isInferredBasionymAuthorship
570
                    );
571

    
572
            isInferredExBasionymAuthorship = updateAuthorshipFieldData(
573
                    taxonName.getExBasionymAuthorship(),
574
                    inferExBasiomynAuthors(),
575
                    exBasionymAuthorshipField,
576
                    basionymsComboboxSelect,
577
                    isInferredExBasionymAuthorship
578
                    );
579

    
580
        }
581

    
582
        // ------------- Validation and ExCombinationAuthors
583
        isInferredExCombinationAuthorship = updateAuthorshipFieldData(
584
                taxonName.getExCombinationAuthorship(),
585
                inferExCombinationAuthors(),
586
                exCombinationAuthorshipField,
587
                validationField.getValidatedNameComboBox(),
588
                isInferredExCombinationAuthorship
589
                );
590

    
591
        updateFieldVisibility();
592

    
593
    }
594

    
595
//    /**
596
//     *
597
//     */
598
//    protected void updateAuthorshipFieldsVisibility() {
599
//        combinationAuthorshipField.setVisible(!isInferredCombinationAuthorship);
600
//        if(BooleanUtils.isTrue(basionymToggle.getValue())){
601
//            basionymAuthorshipField.setVisible(!isInferredBasionymAuthorship);
602
//            exBasionymAuthorshipField.setVisible(!isInferredExBasionymAuthorship);
603
//        }
604
//    }
605

    
606
    /**
607
     *
608
     * @param authorship
609
     *    the value of the taxonName authorship field
610
     * @param inferredAuthors
611
     *    the value inferred from other fields which may be set as authorship to the taxon name
612
     * @param authorshipField
613
     *    the ui element to edit the taxonName authorship field
614
     * @param updateTriggerField
615
     * @param lastInferredAuthorshipState
616
     * @return
617
     */
618
    protected Boolean updateAuthorshipFieldData(TeamOrPersonBase<?> authorship, TeamOrPersonBase inferredAuthors,
619
            TeamOrPersonField authorshipField, AbstractField updateTriggerField,
620
            Boolean lastInferredAuthorshipState) {
621

    
622
        if(authorship == null){
623
            authorshipField.setValue(inferredAuthors);
624
            lastInferredAuthorshipState = true;
625
        } else {
626
            boolean authorshipMatch = authorship == inferredAuthors;
627
            if(lastInferredAuthorshipState == null){
628
                // initialization of authorshipState, this comes only into account when the editor is just being initialized
629
                lastInferredAuthorshipState = authorshipMatch;
630
            }
631
            if(!authorshipMatch && lastInferredAuthorshipState){
632
                // update the combinationAuthorshipField to follow changes of the nomenclatural reference in case it was autofilled before
633
                authorshipField.setValue(inferredAuthors);
634
                lastInferredAuthorshipState = true;
635
            }
636
        }
637

    
638
        if(updateTriggerField != null){
639
            // IMPORTANT!
640
            // this ChangeListener must be added at this very late point in the editor lifecycle so that it is called after
641
            // the ToOneRelatedEntityReloader which may have been added to the updateTriggerField in the presenters handleViewEntered() method.
642
            // Otherwise we risk multiple representation problems in the hibernate session
643
            if(!authorshipUpdateListeners.containsKey(updateTriggerField)){
644
                ValueChangeListener listener = e ->  {
645
                    logger.debug(" value changed #2");
646
                    updateAuthorshipFields();
647
                };
648
                updateTriggerField.addValueChangeListener(listener);
649
                authorshipUpdateListeners.put(updateTriggerField, listener);
650
            }
651
        }
652

    
653
        return lastInferredAuthorshipState;
654
    }
655

    
656
    /**
657
     * @param rank
658
     * @return
659
     */
660
    private void updateFieldVisibility() {
661

    
662
        // TODO use getField() instead and remove field references
663
        Rank rank = (Rank) rankSelect.getValue();
664

    
665
        boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES());
666
        Boolean withBasionymSection = BooleanUtils.isTrue(basionymToggle.getValue());
667
        Boolean withValidationSection = isSpeciesOrBelow && BooleanUtils.isTrue(validationToggle.getValue());
668

    
669
        if(isModeEnabled(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART)){
670
            if(rank.isInfraSpecific()) {
671
                if(TextField.class.isAssignableFrom(specificEpithetField.getClass())) {
672
                     specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, new LazyComboBox<String>(String.class), 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
673
                }
674
            } else {
675
                if(LazyComboBox.class.isAssignableFrom(specificEpithetField.getClass())) {
676
                    specificEpithetField = replaceComponent("specificEpithet", specificEpithetField, new TextFieldNFix(), 0, specificEpithetFieldRow, 1, specificEpithetFieldRow);
677
               }
678
            }
679
        }
680

    
681
        specificEpithetField.setVisible(isSpeciesOrBelow);
682
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
683
        infraGenericEpithetField.setVisible(rank.isInfraGeneric());
684

    
685
        basionymsComboboxSelect.setVisible(withBasionymSection);
686

    
687
        combinationAuthorshipField.setVisible(isInferredCombinationAuthorship != null && !isInferredCombinationAuthorship);
688
        basionymAuthorshipField.setVisible(withBasionymSection && isInferredBasionymAuthorship != null && !isInferredBasionymAuthorship);
689
        exBasionymAuthorshipField.setVisible(withBasionymSection && isInferredExBasionymAuthorship != null && !isInferredExBasionymAuthorship);
690

    
691
        validationField.setVisible(withValidationSection);
692
        exCombinationAuthorshipField.setVisible(withValidationSection && isInferredExCombinationAuthorship != null && !isInferredExCombinationAuthorship);
693

    
694

    
695
//        if(taxonName != null){
696
//            if(modesActive.contains(TaxonNamePopupEditorMode.AUTOFILL_AUTHORSHIP_DATA)){
697
//            }
698
//        }
699

    
700
        infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
701
        specificEpithetField.setVisible(isSpeciesOrBelow);
702
        infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
703
        genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
704
    }
705

    
706

    
707
    @Override
708
    public void cancel() {
709
        authorshipUpdateListeners.keySet().forEach(field -> field.removeValueChangeListener(authorshipUpdateListeners.get(field)));
710
        super.cancel();
711
    }
712

    
713
    /**
714
     * {@inheritDoc}
715
     */
716
    @Override
717
    public boolean allowAnonymousAccess() {
718
        return false;
719
    }
720

    
721
    /**
722
     * {@inheritDoc}
723
     */
724
    @Override
725
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
726
        return null;
727
    }
728

    
729
    /**
730
     * {@inheritDoc}
731
     */
732
    @Override
733
    public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
734
        return nomReferenceCombobox;
735
    }
736

    
737
    /**
738
     * {@inheritDoc}
739
     */
740
    @Override
741
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
742
        return basionymsComboboxSelect;
743
    }
744

    
745
    /**
746
     * {@inheritDoc}
747
     */
748
    @Override
749
    public ToManyRelatedEntitiesComboboxSelect<TaxonName> getReplacedSynonymsComboboxSelect() {
750
        return replacedSynonymsComboboxSelect;
751
    }
752

    
753
    /**
754
     * {@inheritDoc}
755
     */
756
    @Override
757
    public ListSelect getRankSelect() {
758
        return rankSelect;
759
    }
760

    
761
    /**
762
     * {@inheritDoc}
763
     */
764
    @Override
765
    public AbstractField<String> getGenusOrUninomialField(){
766
        return genusOrUninomialField;
767
    }
768

    
769
    /**
770
     * @return the exBasionymAuthorshipField
771
     */
772
    @Override
773
    public TeamOrPersonField getExBasionymAuthorshipField() {
774
        return exBasionymAuthorshipField;
775
    }
776

    
777
    /**
778
     * @return the basionymAuthorshipField
779
     */
780
    @Override
781
    public TeamOrPersonField getBasionymAuthorshipField() {
782
        return basionymAuthorshipField;
783
    }
784

    
785
    /**
786
     * @return the combinationAuthorshipField
787
     */
788
    @Override
789
    public TeamOrPersonField getCombinationAuthorshipField() {
790
        return combinationAuthorshipField;
791
    }
792

    
793
    /**
794
     * @return the exCombinationAuthorshipField
795
     */
796
    @Override
797
    public TeamOrPersonField getExCombinationAuthorshipField() {
798
        return exCombinationAuthorshipField;
799
    }
800

    
801
    @Override
802
    public NameRelationField getValidationField(){
803
        return validationField;
804
    }
805

    
806
    @Override
807
    public void enableMode(TaxonNamePopupEditorMode mode){
808
            modesActive.add(mode);
809
    }
810

    
811
    @Override
812
    public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
813
        return modesActive.contains(mode);
814
    }
815

    
816
    @Override
817
    public void disableMode(TaxonNamePopupEditorMode mode){
818
        modesActive.remove(mode);
819
    }
820

    
821
    @Override
822
    public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
823
        return modesActive;
824
    }
825

    
826
    @Override
827
    public CheckBox getBasionymToggle() {
828
        return basionymToggle;
829
    }
830

    
831
    /**
832
     * {@inheritDoc}
833
     */
834
    @Override
835
    public void setReadOnly(boolean readOnly) {
836
        boolean basionymToggleReadonly = basionymToggle.isReadOnly();
837
        boolean validationToggleReadonly = validationToggle.isReadOnly();
838
        super.setReadOnly(readOnly);
839
        combinationAuthorshipField.setEditorReadOnly(readOnly);
840
        exCombinationAuthorshipField.setEditorReadOnly(readOnly);
841
        basionymAuthorshipField.setEditorReadOnly(readOnly);
842
        exBasionymAuthorshipField.setEditorReadOnly(readOnly);
843
        // preserve old readonly states if they were true
844
        if(basionymToggleReadonly){
845
            basionymToggle.setReadOnly(true);
846
        }
847
        if(validationToggleReadonly){
848
            validationToggle.setReadOnly(true);
849
        }
850
    }
851

    
852
    /**
853
     * @return the infraGenericEpithetField
854
     */
855
    @Override
856
    public AbstractField<String> getInfraGenericEpithetField() {
857
        return infraGenericEpithetField;
858
    }
859

    
860
    /**
861
     * @return the specificEpithetField
862
     */
863
    @Override
864
    public AbstractField<String> getSpecificEpithetField() {
865
        return specificEpithetField;
866
    }
867

    
868
    /**
869
     * @return the infraSpecificEpithetField
870
     */
871
    @Override
872
    public AbstractField<String> getInfraSpecificEpithetField() {
873
        return infraSpecificEpithetField;
874
    }
875

    
876

    
877
}
(10-10/13)