Project

General

Profile

Download (41.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.Arrays;
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.lang.StringUtils;
19
import org.apache.log4j.Logger;
20
import org.hibernate.criterion.Restrictions;
21
import org.springframework.context.annotation.Scope;
22
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
23
import org.vaadin.viritin.fields.AbstractElementCollection;
24

    
25
import com.vaadin.data.Property;
26
import com.vaadin.data.util.BeanItemContainer;
27
import com.vaadin.spring.annotation.SpringComponent;
28
import com.vaadin.ui.AbstractField;
29
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
30
import com.vaadin.ui.Field;
31

    
32
import eu.etaxonomy.cdm.api.service.INameService;
33
import eu.etaxonomy.cdm.format.ReferenceEllypsisFormatter;
34
import eu.etaxonomy.cdm.format.ReferenceEllypsisFormatter.LabelType;
35
import eu.etaxonomy.cdm.model.agent.AgentBase;
36
import eu.etaxonomy.cdm.model.agent.Person;
37
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
38
import eu.etaxonomy.cdm.model.common.AnnotationType;
39
import eu.etaxonomy.cdm.model.common.CdmBase;
40
import eu.etaxonomy.cdm.model.common.Language;
41
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
42
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
43
import eu.etaxonomy.cdm.model.name.Rank;
44
import eu.etaxonomy.cdm.model.name.TaxonName;
45
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
46
import eu.etaxonomy.cdm.model.reference.Reference;
47
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
48
import eu.etaxonomy.cdm.model.reference.ReferenceType;
49
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
50
import eu.etaxonomy.cdm.model.term.TermType;
51
import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
52
import eu.etaxonomy.cdm.persistence.dao.common.Restriction.Operator;
53
import eu.etaxonomy.cdm.persistence.dao.initializer.EntityInitStrategy;
54
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
55
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
56
import eu.etaxonomy.cdm.service.TaxonNameStringFilterablePagingProvider;
57
import eu.etaxonomy.cdm.service.UserHelperAccess;
58
import eu.etaxonomy.cdm.service.initstrategies.AgentBaseInit;
59
import eu.etaxonomy.cdm.vaadin.event.EditorActionTypeFilter;
60
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
61
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
62
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
63
import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorActionStrRep;
64
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityButtonUpdater;
65
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityReloader;
66
import eu.etaxonomy.cdm.vaadin.model.name.TaxonNameDTO;
67
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
68
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
69
import eu.etaxonomy.cdm.vaadin.util.ReferenceEllypsisCaptionGenerator;
70
import eu.etaxonomy.cdm.vaadin.view.reference.ReferencePopupEditor;
71
import eu.etaxonomy.cdm.vaadin.view.reference.RegistrationUiReferenceEditorFormConfigurator;
72
import eu.etaxonomy.vaadin.component.CompositeCustomField;
73
import eu.etaxonomy.vaadin.component.ReloadableLazyComboBox;
74
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
75
import eu.etaxonomy.vaadin.component.WeaklyRelatedEntityCombobox;
76
import eu.etaxonomy.vaadin.component.WeaklyRelatedEntityField;
77
import eu.etaxonomy.vaadin.event.FieldReplaceEvent;
78
import eu.etaxonomy.vaadin.mvp.AbstractCdmDTOEditorPresenter;
79
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
80
import eu.etaxonomy.vaadin.mvp.BeanInstantiator;
81
import eu.etaxonomy.vaadin.mvp.BoundField;
82
import eu.etaxonomy.vaadin.ui.view.PopupView;
83
import eu.etaxonomy.vaadin.util.PropertyIdPath;
84

    
85
/**
86
 * @author a.kohlbecker
87
 * @since May 22, 2017
88
 *
89
 */
90
@SpringComponent
91
@Scope("prototype")
92
public class TaxonNameEditorPresenter extends AbstractCdmDTOEditorPresenter<TaxonNameDTO, TaxonName, TaxonNamePopupEditorView> {
93

    
94
    private static final long serialVersionUID = -3538980627079389221L;
95

    
96
    private static final EnumSet<CRUD> SUB_EDITOR_CRUD = EnumSet.of(CRUD.UPDATE, CRUD.DELETE);
97

    
98
    private static final List<String> RELATED_NAME_INIT_STRATEGY = Arrays.asList(
99
            "$",
100
            "relationsFromThisName",
101
            "relationsToThisName.type",
102
            "homotypicalGroup.typifiedNames"
103
            );
104

    
105
    public static List<String> REFERENCE_INIT_STRATEGY = ReferenceEllypsisFormatter.INIT_STRATEGY;
106

    
107

    
108
    private static final Logger logger = Logger.getLogger(TaxonNameEditorPresenter.class);
109

    
110
    private CdmFilterablePagingProvider<Reference, Reference> nomReferencePagingProvider;
111

    
112
    private Reference publishedUnit;
113

    
114
    private BeanInstantiator<Reference> newReferenceInstantiator;
115

    
116
    private Map<ReferencePopupEditor, NomenclaturalStatusRow> statusTypeReferencePopupEditorsRowMap = new HashMap<>();
117

    
118
    private TaxonNameStringFilterablePagingProvider genusOrUninomialPartPagingProvider;
119

    
120
    private TaxonNameStringFilterablePagingProvider specificEpithetPartPagingProvider;
121

    
122
    private Property.ValueChangeListener refreshSpecificEpithetComboBoxListener;
123

    
124
    private CdmFilterablePagingProvider<TaxonName, TaxonName> relatedNamePagingProvider;
125

    
126
    private CdmFilterablePagingProvider<TaxonName, TaxonName> orthographicVariantNamePagingProvider;
127

    
128
    private Restriction<Reference> orthographicCorrectionRestriction;
129

    
130
    private Integer taxonNameId;
131

    
132
    /**
133
     * {@inheritDoc}
134
     */
135
    @SuppressWarnings("serial")
136
    @Override
137
    public void handleViewEntered() {
138

    
139
        super.handleViewEntered();
140

    
141
        getView().getRankSelect().setContainerDataSource(cdmBeanItemContainerFactory.buildBeanItemContainer(TermType.Rank));
142
        getView().getRankSelect().setItemCaptionPropertyId("label");
143

    
144
        CdmFilterablePagingProvider<AgentBase, TeamOrPersonBase> termOrPersonPagingProvider = pagingProviderFactory.teamOrPersonPagingProvider();
145
        termOrPersonPagingProvider.setInitStrategy(AgentBaseInit.TEAM_OR_PERSON_INIT_STRATEGY);
146
        CdmFilterablePagingProvider<AgentBase, Person> personPagingProvider = pagingProviderFactory.personPagingProvider();
147

    
148
        getView().getCombinationAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
149
        getView().getCombinationAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
150

    
151
        getView().getExCombinationAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
152
        getView().getExCombinationAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
153

    
154
        getView().getBasionymAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
155
        getView().getBasionymAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
156

    
157
        getView().getExBasionymAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
158
        getView().getExBasionymAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
159

    
160
        nomReferencePagingProvider = pagingProviderFactory.referencePagingProvider();
161
        nomReferencePagingProvider.setInitStrategy(REFERENCE_INIT_STRATEGY);
162
        getView().getNomReferenceCombobox().loadFrom(nomReferencePagingProvider, nomReferencePagingProvider, nomReferencePagingProvider.getPageSize());
163
        getView().getNomReferenceCombobox().setNestedButtonStateUpdater(new ToOneRelatedEntityButtonUpdater<Reference>(getView().getNomReferenceCombobox()));
164
        getView().getNomReferenceCombobox().getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.NOMENCLATURAL, getView().getNomReferenceCombobox().getSelect()));
165
        getView().getNomReferenceCombobox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getNomReferenceCombobox(), this));
166
        getView().getNomReferenceCombobox().getSelect().addValueChangeListener( e -> updateOrthographicCorrectionRestriction());
167

    
168
        CdmFilterablePagingProvider<Reference, Reference> icbnCodesPagingProvider = pagingProviderFactory.referencePagingProvider();
169
        // @formatter:off
170
        // TODO use markers on references instead of isbn. The marker type MarkerType.NOMENCLATURAL_RELEVANT() has already prepared (#7466)
171
        icbnCodesPagingProvider.getCriteria().add(Restrictions.in("isbn", new String[]{
172
                "3-904144-22-7",     // Saint Louis Code
173
                "3-906166-48-1",     // Vienna Code
174
                "978-3-87429-425-6", // Melbourne Code
175
                "978-3-946583-16-5", // Shenzhen Code
176
                "0-85301-006-4"      // ICZN 1999
177
                // ICNB
178
        }));
179
        // @formatter:on
180

    
181
        statusTypeReferencePopupEditorsRowMap.clear();
182
        getView().getNomStatusCollectionField().addElementAddedListener(e -> addNomenclaturalStatus(e.getElement()));
183
        getView().getNomStatusCollectionField().setEditorInstantiator(new AbstractElementCollection.Instantiator<NomenclaturalStatusRow>() {
184

    
185
            @Override
186
            public NomenclaturalStatusRow create() {
187
                NomenclaturalStatusRow row = new NomenclaturalStatusRow();
188

    
189
                BeanItemContainer<DefinedTermBase> buildBeanItemContainer = cdmBeanItemContainerFactory.buildBeanItemContainer(NomenclaturalStatusType.ALTERNATIVE().getVocabulary().getUuid());
190
                row.type.setContainerDataSource(buildBeanItemContainer);
191
                row.type.setItemCaptionMode(ItemCaptionMode.EXPLICIT);
192
                for(DefinedTermBase term : buildBeanItemContainer.getItemIds()){
193
                    row.type.setItemCaption(term, term.getPreferredRepresentation(Language.DEFAULT()).getAbbreviatedLabel());
194
                }
195
                row.type.setNullSelectionAllowed(false);
196

    
197
                row.citation.loadFrom(icbnCodesPagingProvider, icbnCodesPagingProvider, icbnCodesPagingProvider.getPageSize());
198
                row.citation.getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.NOMENCLATURAL, row.citation.getSelect()));
199
                row.citation.getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<Reference>(row.citation.getSelect(),
200
                        TaxonNameEditorPresenter.this));
201
                row.citation.addClickListenerAddEntity(e -> doReferenceEditorAdd(row));
202
                row.citation.addClickListenerEditEntity(e -> {
203
                    if(row.citation.getValue() != null){
204
                        doReferenceEditorEdit(row);
205
                    }
206
                });
207

    
208
                getView().applyDefaultComponentStyle(row.components());
209

    
210
                return row;
211
            }
212
        });
213

    
214
        relatedNamePagingProvider = pagingProviderFactory.taxonNamesWithoutOrthophicIncorrect();
215
        relatedNamePagingProvider.setInitStrategy(RELATED_NAME_INIT_STRATEGY);
216
        getView().getBasionymComboboxSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
217
        getView().getBasionymComboboxSelect().setPagingProviders(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize(), this);
218

    
219
        getView().getReplacedSynonymsComboboxSelect().setCaptionGenerator( new CdmTitleCacheCaptionGenerator<TaxonName>());
220
        getView().getReplacedSynonymsComboboxSelect().setPagingProviders(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize(), this);
221

    
222
        getView().getValidationField().getRelatedNameComboBox().getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
223
        getView().getValidationField().getRelatedNameComboBox().loadFrom(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize());
224
        getView().getValidationField().getRelatedNameComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getValidationField().getRelatedNameComboBox(), this));
225
        getView().getValidationField().getCitatonComboBox().getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.BIBLIOGRAPHIC, getView().getValidationField().getCitatonComboBox().getSelect()));
226
        getView().getValidationField().getCitatonComboBox().loadFrom(icbnCodesPagingProvider, icbnCodesPagingProvider, icbnCodesPagingProvider.getPageSize());
227
        getView().getValidationField().getCitatonComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getValidationField().getCitatonComboBox(), this));
228

    
229
        getView().getOrthographicVariantField().getRelatedNameComboBox().getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
230
        getView().getOrthographicVariantField().getRelatedNameComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getOrthographicVariantField().getRelatedNameComboBox(), this));
231
        getView().getOrthographicVariantField().getRelatedNameComboBox().loadFrom(relatedNamePagingProvider, relatedNamePagingProvider, relatedNamePagingProvider.getPageSize());
232
        // The Mode TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION will be handled in the updateOrthographicCorrectionRestriction() method
233
        getView().getOrthographicVariantField().getCitatonComboBox().getSelect().setCaptionGenerator(new ReferenceEllypsisCaptionGenerator(LabelType.BIBLIOGRAPHIC, getView().getOrthographicVariantField().getCitatonComboBox().getSelect()));
234
        getView().getOrthographicVariantField().getCitatonComboBox().loadFrom(icbnCodesPagingProvider, icbnCodesPagingProvider, icbnCodesPagingProvider.getPageSize());
235
        getView().getOrthographicVariantField().getCitatonComboBox().getSelect().addValueChangeListener(new ToOneRelatedEntityReloader<>(getView().getOrthographicVariantField().getCitatonComboBox(), this));
236

    
237
        getView().getAnnotationsField().setAnnotationTypeItemContainer(cdmBeanItemContainerFactory.buildBeanItemContainer(
238
                AnnotationType.EDITORIAL().getVocabulary().getUuid()));
239
    }
240

    
241
    /**
242
     * @param element
243
     * @return
244
     */
245
    private void addNomenclaturalStatus(NomenclaturalStatus element) {
246
        // Nothing to do
247
    }
248

    
249
    @Override
250
    protected void adaptDataProviders() {
251
        updateOrthographicCorrectionRestriction();
252
    }
253

    
254
    private void updateOrthographicCorrectionRestriction() {
255

    
256
        if(getView().isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
257
            if(orthographicVariantNamePagingProvider == null){
258
                orthographicVariantNamePagingProvider = new CdmFilterablePagingProvider<TaxonName, TaxonName>(getRepo().getNameService());
259
                orthographicVariantNamePagingProvider.setInitStrategy(RELATED_NAME_INIT_STRATEGY);
260
                orthographicVariantNamePagingProvider.addRestriction(new Restriction<>("id", Operator.AND_NOT, null, taxonNameId));
261
                getView().getOrthographicVariantField().getRelatedNameComboBox().loadFrom(orthographicVariantNamePagingProvider, orthographicVariantNamePagingProvider, orthographicVariantNamePagingProvider.getPageSize());
262
            }
263
            Reference nomReference = getView().getNomReferenceCombobox().getValue();
264
            if(nomReference == null && orthographicCorrectionRestriction != null){
265
                orthographicVariantNamePagingProvider.getRestrictions().remove(orthographicCorrectionRestriction);
266
            } else {
267
                if(orthographicCorrectionRestriction == null){
268
                    orthographicCorrectionRestriction = new Restriction<>("nomenclaturalReference", Operator.AND, null, nomReference);
269
                    orthographicVariantNamePagingProvider.addRestriction(orthographicCorrectionRestriction);
270
                } else{
271
                    orthographicCorrectionRestriction.setValues(Arrays.asList(nomReference));
272
                }
273
            }
274
            getView().getOrthographicVariantField().getRelatedNameComboBox().getSelect().refresh();
275
        }
276
    }
277

    
278
    @Override
279
    protected TaxonName loadCdmEntity(UUID identifier) {
280

    
281
        EntityInitStrategy initStrategy = new EntityInitStrategy(
282
                Arrays.asList(
283
                "$",
284
                "annotations.type",
285
                "annotations.*", // needed as log as we are using a table in FilterableAnnotationsField
286
                "rank.vocabulary", // needed for comparing ranks
287

    
288
                "nomenclaturalReference",
289

    
290
                "status.type",
291
                "status.citation",
292

    
293
                "combinationAuthorship",
294
                "exCombinationAuthorship",
295
                "basionymAuthorship",
296
                "exBasionymAuthorship",
297

    
298
                // basionyms: relationsToThisName.fromName
299
                "relationsToThisName.type",
300
                "relationsToThisName.fromName.rank",
301
                "relationsToThisName.fromName.combinationAuthorship",
302
                "relationsToThisName.fromName.exCombinationAuthorship",
303
                "relationsToThisName.fromName.nomenclaturalReference.authorship",
304
                "relationsToThisName.fromName.nomenclaturalReference.inReference.authorship",
305
                "relationsToThisName.fromName.nomenclaturalReference.inReference.inReference.inReference.authorship",
306
                "relationsToThisName.fromName.relationsToThisName",
307
                "relationsToThisName.fromName.relationsFromThisName",
308
                "relationsToThisName.citation",
309
                "relationsFromThisName",
310
                "homotypicalGroup.typifiedNames"
311
                )
312
              );
313
        initStrategy.extend("nomenclaturalReference", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
314
        initStrategy.extend("status.citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
315
        initStrategy.extend("relationsToThisName.citation", ReferenceEllypsisFormatter.INIT_STRATEGY, false);
316

    
317
        TaxonName taxonName;
318
        if(identifier != null){
319
            taxonName = getRepo().getNameService().load(identifier, initStrategy.getPropertyPaths());
320
        } else {
321
            taxonName = createCdmEntity();
322
        }
323

    
324
        if(getView().isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY)){
325
            Reference nomRef = taxonName.getNomenclaturalReference();
326

    
327
            //getView().getNomReferenceCombobox().setEnabled(nomRef.isOfType(ReferenceType.Section));
328
            publishedUnit = nomRef;
329
            if(publishedUnit != null){
330
                while(publishedUnit.isOfType(ReferenceType.Section) && publishedUnit.getInReference() != null){
331
                    publishedUnit = nomRef.getInReference();
332
                }
333
                // reduce available references to those which are sections of the publishedUnit and the publishedUnit itself
334
                // nomReferencePagingProvider
335
                nomReferencePagingProvider.getCriteria().add(Restrictions.or(
336
                        Restrictions.and(Restrictions.eq("inReference", publishedUnit), Restrictions.eq("type", ReferenceType.Section)),
337
                        Restrictions.idEq(publishedUnit.getId())
338
                        )
339
                );
340
            }
341
            // and remove the empty option
342
            getView().getNomReferenceCombobox().getSelect().setNullSelectionAllowed(false);
343

    
344
            // new Reference only a sub sections of the publishedUnit
345
            newReferenceInstantiator = new BeanInstantiator<Reference>() {
346
                @Override
347
                public Reference createNewBean() {
348
                    Reference newRef = ReferenceFactory.newSection();
349
                    newRef.setInReference(publishedUnit);
350
                    return newRef;
351
                }
352
            };
353

    
354
        }
355

    
356
        taxonNameId = Integer.valueOf(taxonName.getId());
357
        relatedNamePagingProvider.addRestriction(new Restriction<>("id", Operator.AND_NOT, null, taxonNameId));
358

    
359
        return taxonName;
360
    }
361

    
362
    /**
363
     * {@inheritDoc}
364
     */
365
    @Override
366
    protected void guaranteePerEntityCRUDPermissions(UUID identifier) {
367
        if(crud != null){
368
            newAuthorityCreated = UserHelperAccess.userHelper().createAuthorityForCurrentUser(TaxonName.class, identifier, crud, null);
369
        }
370

    
371
    }
372

    
373
    /**
374
     * {@inheritDoc}
375
     */
376
    @Override
377
    protected void guaranteePerEntityCRUDPermissions(TaxonName bean) {
378
        if(crud != null){
379
            newAuthorityCreated = UserHelperAccess.userHelper().createAuthorityForCurrentUser(bean, crud, null);
380
        }
381
    }
382

    
383
    /**
384
     * {@inheritDoc}
385
     */
386
    @Override
387
    protected INameService getService() {
388
        return getRepo().getNameService();
389
    }
390

    
391

    
392
    public void doReferenceEditorAdd(NomenclaturalStatusRow row) {
393

    
394
        ReferencePopupEditor referencePopupEditor = openPopupEditor(ReferencePopupEditor.class, null);
395

    
396
        referencePopupEditor.withReferenceTypes(RegistrationUIDefaults.MEDIA_REFERENCE_TYPES);
397
        referencePopupEditor.grantToCurrentUser(SUB_EDITOR_CRUD);
398
        referencePopupEditor.withDeleteButton(true);
399
        referencePopupEditor.loadInEditor(null);
400

    
401
        statusTypeReferencePopupEditorsRowMap.put(referencePopupEditor, row);
402
    }
403

    
404
    public void doReferenceEditorEdit(NomenclaturalStatusRow row) {
405

    
406
        ReferencePopupEditor referencePopupEditor = openPopupEditor(ReferencePopupEditor.class, null);
407
        referencePopupEditor.withReferenceTypes(RegistrationUIDefaults.MEDIA_REFERENCE_TYPES);
408
        referencePopupEditor.grantToCurrentUser(SUB_EDITOR_CRUD);
409
        referencePopupEditor.withDeleteButton(true);
410
        referencePopupEditor.loadInEditor(row.citation.getValue().getUuid());
411

    
412
        statusTypeReferencePopupEditorsRowMap.put(referencePopupEditor, row);
413
    }
414
    /**
415
     * @param referenceEditorPopup
416
     */
417
    private void configureReferencePopupEditor(ReferencePopupEditor referenceEditorPopup, UUID referenceUUID) {
418
        boolean nomRefSectionEditingOnly = getView().isModeEnabled(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
419
        if(nomRefSectionEditingOnly){
420
            referenceEditorPopup.setBeanInstantiator(newReferenceInstantiator);
421
        }
422

    
423
        // TODO this should be configurable per UI - RegistrationUiReferenceEditorFormConfigurator as spring bean, different spring profiles
424
        referenceEditorPopup.setEditorComponentsConfigurator(new RegistrationUiReferenceEditorFormConfigurator(nomRefSectionEditingOnly && newReferenceInstantiator != null));
425

    
426
        referenceEditorPopup.loadInEditor(referenceUUID);
427
        if(!nomRefSectionEditingOnly){
428
            referenceEditorPopup.getTypeSelect().setValue(ReferenceType.Article);
429
        }
430
    }
431

    
432
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
433
    public void onReferenceEditorActionAdd(ReferenceEditorAction event) {
434

    
435
        if(getView() == null || event.getSourceView() != getView() ){
436
            return;
437
        }
438

    
439
        ReferencePopupEditor referenceEditorPopup = openPopupEditor(ReferencePopupEditor.class, event);
440

    
441
        referenceEditorPopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
442
        referenceEditorPopup.withDeleteButton(true);
443
        configureReferencePopupEditor(referenceEditorPopup, null);
444
    }
445

    
446

    
447
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
448
    public void onReferenceEditorActionEdit(ReferenceEditorAction event) {
449

    
450

    
451
        if(!isFromOwnView(event)){
452
            return;
453
        }
454
        ReferencePopupEditor referenceEditorPopup = openPopupEditor(ReferencePopupEditor.class, event);
455

    
456
        referenceEditorPopup.withDeleteButton(true);
457
        configureReferencePopupEditor(referenceEditorPopup, event.getEntityUuid());
458
    }
459

    
460
    @EventBusListenerMethod
461
    public void onFieldReplaceEvent(FieldReplaceEvent<String> event){
462

    
463
        PropertyIdPath boundPropertyIdPath = boundPropertyIdPath(event.getNewField());
464
        if(boundPropertyIdPath != null){
465
            TaxonNameDTO taxonNamedto = ((AbstractPopupEditor<TaxonNameDTO, AbstractCdmDTOEditorPresenter<TaxonNameDTO, TaxonName,?>>)getView()).getBean();
466
            if(boundPropertyIdPath.matches("specificEpithet")){
467
                AbstractField<String> genusOrUninomialField = getView().getGenusOrUninomialField();
468
                if(event.getNewField() instanceof CompositeCustomField){
469
                    if(specificEpithetPartPagingProvider == null){
470
                        specificEpithetPartPagingProvider = new TaxonNameStringFilterablePagingProvider(getRepo().getNameService(), Rank.SPECIES());
471
                    }
472
                    specificEpithetPartPagingProvider.listenToFields(
473
                            genusOrUninomialField,
474
                            null, null, null);
475
                    specificEpithetPartPagingProvider.excludeNames(taxonNamedto.cdmEntity());
476
                    specificEpithetPartPagingProvider.updateFromFields();
477
                    WeaklyRelatedEntityCombobox<TaxonName> specificEpithetField = (WeaklyRelatedEntityCombobox<TaxonName>)event.getNewField();
478
                    refreshSpecificEpithetComboBoxListener = e -> { specificEpithetField.getSelect().refresh(); specificEpithetField.setValue(null);};
479
                    specificEpithetField.loadFrom(specificEpithetPartPagingProvider, specificEpithetPartPagingProvider, specificEpithetPartPagingProvider.getPageSize());
480
                    specificEpithetField.setValue(event.getOldField().getValue());
481
                    specificEpithetField.reload();
482
                    genusOrUninomialField.addValueChangeListener(refreshSpecificEpithetComboBoxListener);
483
                } else {
484
                    if(specificEpithetPartPagingProvider != null){
485
                        specificEpithetPartPagingProvider.unlistenAllFields();
486
                    }
487
                    if(refreshSpecificEpithetComboBoxListener != null){
488
                        genusOrUninomialField.removeValueChangeListener(refreshSpecificEpithetComboBoxListener);
489
                        refreshSpecificEpithetComboBoxListener = null;
490
                    }
491
                }
492
            } else if(boundPropertyIdPath.matches("genusOrUninomial")) {
493
                if(event.getNewField() instanceof CompositeCustomField){
494
                    if(genusOrUninomialPartPagingProvider  == null){
495
                        genusOrUninomialPartPagingProvider = new TaxonNameStringFilterablePagingProvider(getRepo().getNameService());
496
                    }
497
                    genusOrUninomialPartPagingProvider.listenToFields(
498
                                null,
499
                                getView().getInfraGenericEpithetField(),
500
                                getView().getSpecificEpithetField(),
501
                                getView().getInfraSpecificEpithetField()
502
                               );
503
                    genusOrUninomialPartPagingProvider.excludeNames(taxonNamedto.cdmEntity());
504
                    WeaklyRelatedEntityCombobox<TaxonName> genusOrUninomialField = (WeaklyRelatedEntityCombobox<TaxonName>)event.getNewField();
505
                    genusOrUninomialField.loadFrom(genusOrUninomialPartPagingProvider, genusOrUninomialPartPagingProvider, genusOrUninomialPartPagingProvider.getPageSize());
506
                    genusOrUninomialField.setValue(event.getOldField().getValue());
507
                    genusOrUninomialField.reload();
508
                }else {
509
                    if(genusOrUninomialPartPagingProvider != null){
510
                        genusOrUninomialPartPagingProvider.unlistenAllFields();
511
                    }
512
                }
513

    
514
            }
515
        }
516

    
517
    }
518

    
519
    @EventBusListenerMethod
520
    public void onEntityChangeEvent(EntityChangeEvent<?> event){
521

    
522
        if(event.getSourceView() instanceof AbstractPopupEditor) {
523

    
524
            BoundField boundTargetField = boundTargetField((PopupView) event.getSourceView());
525

    
526
            if(boundTargetField != null){
527
                if(boundTargetField.matchesPropertyIdPath("genusOrUninomial")){
528
                    if(event.isCreateOrModifiedType()){
529
                        getCache().load(event.getEntity());
530
                        if(getView().getGenusOrUninomialField() instanceof WeaklyRelatedEntityCombobox){
531
                            WeaklyRelatedEntityCombobox<TaxonName> weaklyRelatedEntityCombobox = (WeaklyRelatedEntityCombobox<TaxonName>)getView().getGenusOrUninomialField();
532
                            weaklyRelatedEntityCombobox.setValue(((TaxonName)event.getEntity()).getGenusOrUninomial());
533
                            // NOTE: in contrast to the ToOneRelatedEntityCombobox the .discard() does not
534
                            // work here since no datasource is bound to the field, see weaklyRelatedEntityCombobox.reload()
535
                            weaklyRelatedEntityCombobox.updateButtons();
536
                        }
537
                    }
538
                } else
539
                if(boundTargetField.matchesPropertyIdPath("specificEpithet")){
540
                    if(event.isCreateOrModifiedType()){
541
                        getCache().load(event.getEntity());
542
                        if(getView().getSpecificEpithetField() instanceof WeaklyRelatedEntityCombobox){
543
                            WeaklyRelatedEntityCombobox<TaxonName> weaklyRelatedEntityCombobox = (WeaklyRelatedEntityCombobox<TaxonName>)getView().getSpecificEpithetField();
544
                            getView().getSpecificEpithetField().setValue(((TaxonName)event.getEntity()).getSpecificEpithet());
545
                            weaklyRelatedEntityCombobox.reload();
546
                            // NOTE: in contrast to the ToOneRelatedEntityCombobox the .discard() does not
547
                            // work here since no datasource is bound to the field, see weaklyRelatedEntityCombobox.reload()
548
                            weaklyRelatedEntityCombobox.updateButtons();
549
                        }
550
                    }
551
                } else
552
                if(boundTargetField.matchesPropertyIdPath("nomenclaturalReference")){
553
                    if(event.isCreateOrModifiedType()){
554
                        getCache().load(event.getEntity());
555
                        if(event.isCreatedType()){
556
                            getView().getNomReferenceCombobox().setValue((Reference) event.getEntity());
557
                        } else {
558
                            getView().getNomReferenceCombobox().reload(); // refreshSelectedValue(modifiedReference);
559
                        }
560
                        getView().getCombinationAuthorshipField().discard(); //refresh from the datasource
561
                        getView().updateAuthorshipFields();
562
                    }
563
                } else
564
                if(boundTargetField.matchesPropertyIdPath("validationFor.otherName") || boundTargetField.matchesPropertyIdPath("orthographicVariant.otherName")){
565
                    ReloadableLazyComboBox<TaxonName> otherNameField = asReloadableLazyComboBox(boundTargetField.getField(TaxonName.class));
566
                    TaxonName otherName = (TaxonName) event.getEntity();
567
                    if(event.isCreateOrModifiedType()){
568
                        getCache().load(otherName);
569
                        if(event.isCreatedType()){
570
                            // TODO use reloadWith((TaxonName) event.getEntity()); also in this case?
571
                            otherNameField.setValue(otherName);
572
                        } else {
573
                            otherNameField.reloadWith(otherName);
574
                        }
575

    
576
                    } else
577
                    if(event.isRemovedType()){
578
                        otherNameField.setValue(null);
579
                    }
580
                } else
581
                if(boundTargetField.matchesPropertyIdPath("basionyms")){
582
                    ReloadableLazyComboBox<TaxonName> basionymSourceField = asReloadableLazyComboBox(boundTargetField.getField(TaxonName.class));
583
                    if(event.isCreateOrModifiedType()){
584
                        getCache().load(event.getEntity());
585
                        if(event.isCreatedType()){
586
                            // TODO use reloadWith((TaxonName) event.getEntity()); also in this case?
587
                            basionymSourceField .setValue((TaxonName) event.getEntity());
588
                        } else {
589
                            basionymSourceField.reloadWith((TaxonName) event.getEntity());
590
                        }
591
                        getView().getBasionymAuthorshipField().discard(); //refresh from the datasource
592
                        getView().getExBasionymAuthorshipField().discard(); //refresh from the datasource
593
                        getView().updateAuthorshipFields();
594
                    } else
595
                    if(event.isRemovedType()){
596
                        basionymSourceField.setValue(null);
597
                        getView().updateAuthorshipFields();
598
                    }
599
                } else
600
                if(boundTargetField.matchesPropertyIdPath("replacedSynonyms")){
601
                    ReloadableLazyComboBox<TaxonName> replacedSynonyms = asReloadableLazyComboBox(boundTargetField.getField(TaxonName.class));
602
                    if(event.isCreateOrModifiedType()){
603
                        getCache().load(event.getEntity());
604
                        if(event.isCreatedType()){
605
                            // TODO use reloadWith((TaxonName) event.getEntity()); also in this case?
606
                            replacedSynonyms .setValue((TaxonName) event.getEntity());
607
                        } else {
608
                            replacedSynonyms.reloadWith((TaxonName) event.getEntity());
609
                        }
610
                        getView().getExCombinationAuthorshipField().discard(); //refresh from the datasource
611
                        getView().updateAuthorshipFields();
612
                    } else
613
                    if(event.isRemovedType()){
614
                        replacedSynonyms.setValue(null);
615
                        getView().updateAuthorshipFields();
616
                    }
617
                }
618

    
619
            }
620
        }
621
    }
622

    
623
    protected <CDM extends CdmBase> ReloadableLazyComboBox<CDM> asReloadableLazyComboBox(Field<CDM> field){
624

    
625
        if(field instanceof ToOneRelatedEntityCombobox){
626
            field = ((ToOneRelatedEntityCombobox<CDM>)field).getSelect();
627
        }
628
        return (ReloadableLazyComboBox<CDM>)field;
629
    }
630

    
631

    
632

    
633
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
634
    public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event) {
635

    
636
        if(getView() == null || event.getSourceView() != getView() ){
637
            return;
638
        }
639

    
640
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
641

    
642
        if(boundPropertyId != null){
643
            if(boundPropertyId.matches("validationFor.otherName") || boundPropertyId.matches("basionyms") || boundPropertyId.matches("replacedSynonyms")  || boundPropertyId.matches("orthographicVariant.otherName")){
644
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
645
                namePopup.withDeleteButton(true);
646
                getView().getModesActive().stream()
647
                    .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
648
                    .forEach(m -> namePopup.enableMode(m));
649
                if(boundPropertyId.matches("orthographicVariant.otherName") && getView().isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
650
                    namePopup.enableMode(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
651
                    namePopup.disableMode(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART);
652
                    namePopup.getOrthographicVariantToggle().setVisible(false);
653
                }
654
                namePopup.loadInEditor(event.getEntityUuid());
655
            }
656
        }
657
    }
658

    
659
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Edit.class)
660
    public void onTaxonNameEditorActionStrRepEdit(TaxonNameEditorActionStrRep event) {
661

    
662
        if(getView() == null || event.getSourceView() != getView() ){
663
            return;
664
        }
665

    
666
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
667

    
668
        if(boundPropertyId != null){
669
            if(boundPropertyId.matches("genusOrUninomial") || boundPropertyId.matches("specificEpithet")){
670
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
671
                namePopup.withDeleteButton(true);
672
                getView().getModesActive().stream()
673
                    .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
674
                    .forEach(m -> namePopup.enableMode(m));
675
                namePopup.loadInEditor(event.getEntityUuid());
676
            }
677
        }
678
    }
679

    
680
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
681
    public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event) {
682

    
683
        if(getView() == null || event.getSourceView() != getView() ){
684
            return;
685
        }
686

    
687
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
688

    
689
        if(boundPropertyId != null){
690
            if(boundPropertyId.matches("validationFor.otherName") || boundPropertyId.matches("basionyms") || boundPropertyId.matches("replacedSynonyms") || boundPropertyId.matches("orthographicVariant.otherName")){
691
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
692
                namePopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
693
                namePopup.withDeleteButton(true);
694
                getView().getModesActive().stream()
695
                        .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
696
                        .forEach(m -> namePopup.enableMode(m));
697
                if(boundPropertyId.matches("orthographicVariant.otherName") && getView().isModeEnabled(TaxonNamePopupEditorMode.ORTHOGRAPHIC_CORRECTION)){
698
                    namePopup.enableMode(TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY);
699
                    namePopup.disableMode(TaxonNamePopupEditorMode.VALIDATE_AGAINST_HIGHER_NAME_PART);
700
                    Reference nomrefPreset = (Reference)((AbstractPopupEditor<TaxonNameDTO, TaxonNameEditorPresenter>)getView()).getBean().getNomenclaturalReference();
701
                    namePopup.setCdmEntityInstantiator(new BeanInstantiator<TaxonName>() {
702

    
703
                        @Override
704
                        public TaxonName createNewBean() {
705
                            TaxonName newTaxonName = TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
706
                            newTaxonName.setNomenclaturalReference(getRepo().getReferenceService().load(nomrefPreset.getUuid(), TaxonNameEditorPresenter.REFERENCE_INIT_STRATEGY ));
707
                            return newTaxonName;
708
                        }
709
                    });
710
                    namePopup.getOrthographicVariantToggle().setVisible(false);
711
                }
712
                namePopup.loadInEditor(null);
713
            }
714
        }
715
    }
716

    
717
    @EventBusListenerMethod(filter = EditorActionTypeFilter.Add.class)
718
    public void onTaxonNameEditorActionStrRepAdd(TaxonNameEditorActionStrRep event) {
719

    
720
        if(getView() == null || event.getSourceView() != getView() ){
721
            return;
722
        }
723

    
724
        PropertyIdPath boundPropertyId = boundPropertyIdPath(event.getTarget());
725

    
726
        if(boundPropertyId != null){
727
            if(boundPropertyId.matches("genusOrUninomial") || boundPropertyId.matches("specificEpithet")){
728
                TaxonNamePopupEditor namePopup = openPopupEditor(TaxonNamePopupEditor.class, event);
729
                namePopup.grantToCurrentUser(EnumSet.of(CRUD.UPDATE, CRUD.DELETE));
730
                namePopup.withDeleteButton(true);
731
                getView().getModesActive().stream()
732
                .filter(m -> !TaxonNamePopupEditorMode.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY.equals(m))
733
                .forEach(m -> namePopup.enableMode(m));
734
                namePopup.loadInEditor(null);
735
                if(boundPropertyId.matches("genusOrUninomial")){
736
                    namePopup.getRankSelect().setValue(Rank.GENUS());
737
                }
738
                if(boundPropertyId.matches("specificEpithet")){
739
                    namePopup.getGenusOrUninomialField().setValue(getView().getGenusOrUninomialField().getValue());
740
                    namePopup.getRankSelect().setValue(Rank.SPECIES());
741
                }
742
                if(WeaklyRelatedEntityField.class.isAssignableFrom(event.getTarget().getClass())){
743
                    WeaklyRelatedEntityField<TaxonName> taxoNameField = (WeaklyRelatedEntityField<TaxonName>)event.getTarget();
744
                    if(!taxoNameField.isValueInOptions()){
745
                        String nameString = event.getTarget().getValue();
746
                        if(StringUtils.isNotEmpty(nameString)){
747
                            if(boundPropertyId.matches("genusOrUninomial")){
748
                                namePopup.getGenusOrUninomialField().setValue(nameString);
749
                            }
750
                            if(boundPropertyId.matches("specificEpithet")){
751
                                namePopup.getSpecificEpithetField().setValue(nameString);
752
                            }
753
                        }
754
                    }
755
                }
756
            }
757
        }
758
    }
759

    
760
    /**
761
     * {@inheritDoc}
762
     */
763
    @Override
764
    protected TaxonNameDTO createDTODecorator(TaxonName cdmEntitiy) {
765
        return new TaxonNameDTO(cdmEntitiy);
766
    }
767

    
768
    /**
769
     * {@inheritDoc}
770
     */
771
    @Override
772
    protected BeanInstantiator<TaxonName> defaultCdmEntityInstantiator() {
773
        return new BeanInstantiator<TaxonName>() {
774

    
775
            @Override
776
            public TaxonName createNewBean() {
777
                return  TaxonNameFactory.NewNameInstance(RegistrationUIDefaults.NOMENCLATURAL_CODE, Rank.SPECIES());
778
            }
779
        };
780
    }
781

    
782

    
783

    
784

    
785
}
(11-11/15)