2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.vaadin
.view
.registration
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Arrays
;
13 import java
.util
.Collection
;
14 import java
.util
.EnumSet
;
15 import java
.util
.HashMap
;
16 import java
.util
.HashSet
;
17 import java
.util
.List
;
19 import java
.util
.Objects
;
20 import java
.util
.Optional
;
22 import java
.util
.Stack
;
23 import java
.util
.UUID
;
25 import org
.apache
.log4j
.Logger
;
26 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
27 import org
.vaadin
.spring
.events
.EventScope
;
28 import org
.vaadin
.spring
.events
.annotation
.EventBusListenerMethod
;
30 import com
.vaadin
.spring
.annotation
.SpringComponent
;
31 import com
.vaadin
.spring
.annotation
.ViewScope
;
32 import com
.vaadin
.ui
.AbstractField
;
33 import com
.vaadin
.ui
.Label
;
34 import com
.vaadin
.ui
.UI
;
35 import com
.vaadin
.ui
.VerticalLayout
;
36 import com
.vaadin
.ui
.Window
;
38 import eu
.etaxonomy
.cdm
.api
.service
.config
.RegistrationStatusTransitions
;
39 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RegistrationDTO
;
40 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RegistrationWorkingSet
;
41 import eu
.etaxonomy
.cdm
.api
.service
.exception
.RegistrationValidationException
;
42 import eu
.etaxonomy
.cdm
.api
.service
.name
.TypeDesignationSetManager
.TypeDesignationWorkingSetType
;
43 import eu
.etaxonomy
.cdm
.api
.service
.registration
.IRegistrationWorkingSetService
;
44 import eu
.etaxonomy
.cdm
.api
.utility
.UserHelper
;
45 import eu
.etaxonomy
.cdm
.cache
.CdmTransientEntityAndUuidCacher
;
46 import eu
.etaxonomy
.cdm
.database
.PermissionDeniedException
;
47 import eu
.etaxonomy
.cdm
.model
.ICdmEntityUuidCacher
;
48 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
49 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
50 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
51 import eu
.etaxonomy
.cdm
.model
.name
.Registration
;
52 import eu
.etaxonomy
.cdm
.model
.name
.RegistrationStatus
;
53 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
54 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameFactory
;
55 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
56 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
57 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CRUD
;
58 import eu
.etaxonomy
.cdm
.ref
.EntityReference
;
59 import eu
.etaxonomy
.cdm
.ref
.TypedEntityReference
;
60 import eu
.etaxonomy
.cdm
.service
.CdmBeanItemContainerFactory
;
61 import eu
.etaxonomy
.cdm
.service
.CdmFilterablePagingProvider
;
62 import eu
.etaxonomy
.cdm
.service
.CdmFilterablePagingProviderFactory
;
63 import eu
.etaxonomy
.cdm
.service
.CdmStore
;
64 import eu
.etaxonomy
.cdm
.service
.IRegistrationWorkflowService
;
65 import eu
.etaxonomy
.cdm
.service
.UserHelperAccess
;
66 import eu
.etaxonomy
.cdm
.vaadin
.component
.registration
.RegistrationItem
;
67 import eu
.etaxonomy
.cdm
.vaadin
.component
.registration
.RegistrationStatusFieldInstantiator
;
68 import eu
.etaxonomy
.cdm
.vaadin
.component
.registration
.RegistrationStatusSelect
;
69 import eu
.etaxonomy
.cdm
.vaadin
.event
.EditorActionContext
;
70 import eu
.etaxonomy
.cdm
.vaadin
.event
.EditorActionTypeFilter
;
71 import eu
.etaxonomy
.cdm
.vaadin
.event
.EntityChangeEvent
;
72 import eu
.etaxonomy
.cdm
.vaadin
.event
.ReferenceEditorAction
;
73 import eu
.etaxonomy
.cdm
.vaadin
.event
.RegistrationEditorAction
;
74 import eu
.etaxonomy
.cdm
.vaadin
.event
.ShowDetailsEvent
;
75 import eu
.etaxonomy
.cdm
.vaadin
.event
.ShowDetailsEventEntityTypeFilter
;
76 import eu
.etaxonomy
.cdm
.vaadin
.event
.TaxonNameEditorAction
;
77 import eu
.etaxonomy
.cdm
.vaadin
.event
.TypeDesignationWorkingsetEditorAction
;
78 import eu
.etaxonomy
.cdm
.vaadin
.event
.registration
.RegistrationWorkingsetAction
;
79 import eu
.etaxonomy
.cdm
.vaadin
.permission
.AccessRestrictedView
;
80 import eu
.etaxonomy
.cdm
.vaadin
.ui
.RegistrationUIDefaults
;
81 import eu
.etaxonomy
.cdm
.vaadin
.ui
.config
.TaxonNamePopupEditorConfig
;
82 import eu
.etaxonomy
.cdm
.vaadin
.util
.CdmTitleCacheCaptionGenerator
;
83 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.CachingPresenter
;
84 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.NameTypeDesignationPopupEditor
;
85 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.SpecimenTypeDesignationWorkingsetPopupEditor
;
86 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNameEditorPresenter
;
87 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNamePopupEditor
;
88 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TypeDesignationWorkingsetEditorIdSet
;
89 import eu
.etaxonomy
.cdm
.vaadin
.view
.reference
.ReferencePopupEditor
;
90 import eu
.etaxonomy
.vaadin
.mvp
.AbstractPopupEditor
;
91 import eu
.etaxonomy
.vaadin
.mvp
.AbstractPresenter
;
92 import eu
.etaxonomy
.vaadin
.mvp
.AbstractView
;
93 import eu
.etaxonomy
.vaadin
.mvp
.BeanInstantiator
;
94 import eu
.etaxonomy
.vaadin
.ui
.navigation
.NavigationEvent
;
95 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
;
96 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
.Reason
;
97 import eu
.etaxonomy
.vaadin
.ui
.view
.PopupView
;
100 * @author a.kohlbecker
106 public class RegistrationWorkingsetPresenter
extends AbstractPresenter
<RegistrationWorkingsetView
> implements CachingPresenter
{
108 private static final Logger logger
= Logger
.getLogger(RegistrationWorkingsetPresenter
.class);
110 private static final long serialVersionUID
= 1L;
113 private IRegistrationWorkingSetService regWorkingSetService
;
116 private IRegistrationWorkflowService registrationWorkflowService
;
119 private CdmFilterablePagingProviderFactory pagingProviderFactory
;
122 private CdmBeanItemContainerFactory selectFieldFactory
;
125 private CdmStore cdmStore
;
128 * @return the regWorkingSetService
130 public IRegistrationWorkingSetService
getWorkingSetService() {
131 return regWorkingSetService
;
134 private RegistrationWorkingSet workingset
;
137 * Contains the poupeditor which has been opened to start the registration of a new name as long as it has not been saved or canceled.
138 * There can always only be one popup editor for this purpose.
140 private TaxonNamePopupEditor newNameForRegistrationPopupEditor
= null;
145 private List
<Registration
> newNameBlockingRegistrations
= new ArrayList
<>();
148 * TODO is this still needed? The regitration UUID should be accessible in the popup editor context,
149 * see findRegistrationInContext()
151 private Map
<NameTypeDesignationPopupEditor
, UUID
> nameTypeDesignationPopupEditorRegistrationUUIDMap
= new HashMap
<>();
154 private ICdmEntityUuidCacher cache
;
156 private Collection
<CdmBase
> rootEntities
= new HashSet
<>();
161 public RegistrationWorkingsetPresenter() {
168 * @param doReload reload the workingset from the persistent storage.
169 * Workingsets which are not yet persisted are preserved.
172 protected void refreshView(boolean doReload
) {
173 if(workingset
== null){
174 return; // nothing to do
177 List
<RegistrationDTO
> unpersisted
= new ArrayList
<>();
178 for(RegistrationDTO regDto
: workingset
.getRegistrationDTOs()){
179 if(!regDto
.registration().isPersited()){
180 unpersisted
.add(regDto
);
183 loadWorkingSet(workingset
.getCitationUuid());
184 for(RegistrationDTO regDtoUnpersisted
: unpersisted
){
185 if(!workingset
.getRegistrationDTOs().stream().anyMatch(dto
-> dto
.getUuid().equals(regDtoUnpersisted
.getUuid()))){
186 // only add if the regDtoUnpersisted has not been persisted meanwhile
188 workingset
.add(regDtoUnpersisted
);
189 } catch (RegistrationValidationException e
) {
190 // would never happen here //
202 public void handleViewEntered() {
203 super.handleViewEntered();
204 // TODO currently cannot specify type more precisely, see AbstractSelect
205 // FIXME externalize into class file!!!!!!!!!!!!
206 getView().setStatusComponentInstantiator(new RegistrationStatusFieldInstantiator
<Object
>(){
208 private static final long serialVersionUID
= 7099181280977511048L;
211 public AbstractField
<Object
> create(RegistrationDTO regDto
) {
213 // submitters have GrantedAuthorities like REGISTRATION(PREPARATION).[UPDATE]{ab4459eb-3b96-40ba-bfaa-36915107d59e}
214 UserHelper userHelper
= UserHelperAccess
.userHelper().withCache(getCache());
215 Set
<RegistrationStatus
> availableStatus
= new HashSet
<>();
217 boolean canChangeStatus
= userHelper
.userHasPermission(regDto
.registration(), CRUD
.UPDATE
);
218 availableStatus
.add(regDto
.getStatus());
220 if(userHelper
.userIsAdmin()){
221 availableStatus
.addAll(Arrays
.asList(RegistrationStatus
.values()));
223 availableStatus
.addAll(RegistrationStatusTransitions
.possibleTransitions(regDto
.getStatus()));
227 RegistrationStatusSelect select
= new RegistrationStatusSelect(null, selectFieldFactory
.buildBeanItemContainer(
228 RegistrationStatus
.class,
229 availableStatus
.toArray(new RegistrationStatus
[availableStatus
.size()]))
231 select
.setValue(regDto
.getStatus());
232 select
.addValueChangeListener(e
-> saveRegistrationStatusChange(regDto
.getUuid(), e
.getProperty().getValue()));
233 select
.setEnabled(canChangeStatus
);
234 select
.setNullSelectionAllowed(false);
240 loadWorkingSet(getView().getCitationUuid());
245 private void applyWorkingset(){
246 getView().setWorkingset(workingset
);
247 // PagingProviders and CacheGenerator for the existingNameCombobox
248 activateComboboxes();
251 protected void activateComboboxes() {
252 CdmTitleCacheCaptionGenerator
<TaxonName
> titleCacheGenerator
= new CdmTitleCacheCaptionGenerator
<TaxonName
>();
253 getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenerator
);
254 CdmFilterablePagingProvider
<TaxonName
, TaxonName
> pagingProvider
= pagingProviderFactory
.taxonNamesWithoutOrthophicIncorrect();
255 getView().getAddExistingNameCombobox().loadFrom(pagingProvider
, pagingProvider
, pagingProvider
.getPageSize());
261 protected void loadWorkingSet(UUID referenceUuid
) {
264 workingset
= getWorkingSetService().loadWorkingSetByReferenceUuid(referenceUuid
, true);
265 } catch (RegistrationValidationException error
) {
267 showErrorDialog("Validation Error", error
.getMessage());
268 } catch(PermissionDeniedException e
){
270 ((AccessRestrictedView
)getView()).setAccessDeniedMessage(e
.getMessage());
272 cache
= new CdmTransientEntityAndUuidCacher(this);
273 for(Registration registration
: workingset
.getRegistrations()) {
274 addRootEntity(registration
);
279 * @param errorDialogCaption
280 * @param errorMessage
282 public void showErrorDialog(String errorDialogCaption
, String errorMessage
) {
283 Window errorDialog
= new Window(errorDialogCaption
);
284 errorDialog
.setModal(true);
285 VerticalLayout subContent
= new VerticalLayout();
286 subContent
.setMargin(true);
287 errorDialog
.setContent(subContent
);
288 subContent
.addComponent(new Label(errorMessage
));
289 UI
.getCurrent().addWindow(errorDialog
);
292 private void saveRegistrationStatusChange(UUID uuid
, Object value
) {
293 Registration reg
= getRepo().getRegistrationService().load(uuid
);
295 // registration was not yet persisted, ignore
298 if(value
!= null && value
instanceof RegistrationStatus
){
299 if(!Objects
.equals(value
, reg
.getStatus())){
300 reg
.updateStatusAndDate((RegistrationStatus
)value
);
301 cdmStore
.saveBean(reg
, (AbstractView
)getView());
305 // only log here as error
306 logger
.error("Ivalid attempt to set RegistrationStatus to " + Objects
.toString(value
.toString(), "NULL"));
311 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Add
.class)
312 public void onReferenceEditorActionAdd(ReferenceEditorAction event
) {
314 if(!checkFromOwnView(event
)){
318 ReferencePopupEditor popup
= openPopupEditor(ReferencePopupEditor
.class, event
);
319 popup
.withReferenceTypes(RegistrationUIDefaults
.PRINTPUB_REFERENCE_TYPES
);
320 popup
.loadInEditor(null);
323 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
324 public void onReferenceEditorActionEdit(ReferenceEditorAction event
) {
326 if(!checkFromOwnView(event
)){
329 ReferencePopupEditor popup
= openPopupEditor(ReferencePopupEditor
.class, event
);
330 popup
.withReferenceTypes(RegistrationUIDefaults
.PRINTPUB_REFERENCE_TYPES
);
331 popup
.withDeleteButton(true);
332 popup
.loadInEditor(event
.getEntityUuid());
335 @EventBusListenerMethod
336 public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
337 if(event
.getPopup() instanceof ReferencePopupEditor
){
338 if(event
.getReason().equals(Reason
.SAVE
)){
344 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
345 public void onRegistrationEditorAction(RegistrationEditorAction event
) {
347 if(!checkFromOwnView(event
)){
351 RegistrationPopupEditor popup
= openPopupEditor(RegistrationPopupEditor
.class, event
);
352 popup
.loadInEditor(event
.getEntityUuid());
355 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
356 public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event
) {
358 if(!checkFromOwnView(event
)){
362 TaxonNamePopupEditor popup
= openPopupEditor(TaxonNamePopupEditor
.class, event
);
363 popup
.setParentEditorActionContext(event
.getContext(), event
.getTarget());
364 popup
.withDeleteButton(true);
365 TaxonNamePopupEditorConfig
.configureForNomenclaturalAct(popup
);
366 popup
.loadInEditor(event
.getEntityUuid());
367 if(event
.hasSource() && event
.getSource().isReadOnly()){
368 // avoid resetting readonly to false
369 popup
.setReadOnly(true);
375 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Add
.class)
376 public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event
) {
378 if(!checkFromOwnView(event
)){
382 getView().getAddNewNameRegistrationButton().setEnabled(false);
383 if(newNameForRegistrationPopupEditor
== null){
384 TaxonNamePopupEditor popup
= openPopupEditor(TaxonNamePopupEditor
.class, event
);
385 newNameForRegistrationPopupEditor
= popup
;
386 popup
.setParentEditorActionContext(event
.getContext(), event
.getTarget());
387 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
,CRUD
.DELETE
));
388 popup
.withDeleteButton(true);
389 popup
.setCdmEntityInstantiator(new BeanInstantiator
<TaxonName
>() {
392 public TaxonName
createNewBean() {
393 TaxonName newTaxonName
= TaxonNameFactory
.NewNameInstance(RegistrationUIDefaults
.NOMENCLATURAL_CODE
, Rank
.SPECIES());
394 newTaxonName
.setNomenclaturalReference(getRepo().getReferenceService().load(workingset
.getCitationUuid(), TaxonNameEditorPresenter
.REFERENCE_INIT_STRATEGY
));
398 TaxonNamePopupEditorConfig
.configureForNomenclaturalAct(popup
);
399 popup
.loadInEditor(null);
404 * Creates a new <code>Registration</code> for a new name that has just been edited
405 * using a <code>TaxonNamePopupEditor</code>. The popup editor which has been opened to
406 * edit the new name was remembered in <code>newNameForRegistrationPopupEditor</code>.
407 * Any blocking registrations which have been created while editing the new name are
408 * temporarily stored in <code>newNameBlockingRegistrations</code> until the registration
409 * for the first name has been created. Additional new names are created for example
410 * when a new name as basionym, replaced synonym, etc to the new name is created.
412 * See also {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)}).
415 * @throws RegistrationValidationException
417 @EventBusListenerMethod
418 public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event
) {
419 if(event
.getPopup() instanceof TaxonNamePopupEditor
){
420 Registration registration
= null;
421 boolean doRefreshView
= false;
422 if(newNameForRegistrationPopupEditor
!= null && event
.getPopup().equals(newNameForRegistrationPopupEditor
)){
423 if(event
.getReason().equals(Reason
.SAVE
)){
425 TaxonName taxonName
= newNameForRegistrationPopupEditor
.getBean().cdmEntity();
426 registration
= registrationWorkflowService
.createRegistration(taxonName
, newNameBlockingRegistrations
);
427 loadWorkingSet(workingset
.getCitationUuid());
430 doRefreshView
= true;
431 getView().getAddNewNameRegistrationButton().setEnabled(true);
434 // nullify and clear the memory on this popup editor in any case (SAVE, CANCEL, DELETE)
435 newNameForRegistrationPopupEditor
= null;
436 newNameBlockingRegistrations
.clear();
437 getView().getAddNewNameRegistrationButton().setEnabled(true);
440 if(registration
== null){
441 // no new registration has been created above, so there must be an existing one.
442 registration
= findRegistrationInContext(event
.getPopup());
445 // Check if the other names used in the context of the name are registered yet.
446 TaxonNamePopupEditor nameEditor
= (TaxonNamePopupEditor
)event
.getPopup();
447 Set
<TaxonName
> namesToCheck
= new HashSet
<>();
449 namesToCheck
.addAll(nameEditor
.getBasionymComboboxSelect().getValue());
450 namesToCheck
.addAll(nameEditor
.getReplacedSynonymsComboboxSelect().getValue());
451 namesToCheck
.add(nameEditor
.getValidationField().getRelatedNameComboBox().getValue());
452 namesToCheck
.add(nameEditor
.getOrthographicVariantField().getRelatedNameComboBox().getValue());
454 for(TaxonName name
: namesToCheck
){
457 doRefreshView
|= registrationWorkflowService
.addBlockingRegistration(name
.getUuid(), registration
) != null;
461 refreshView(doRefreshView
);
467 * Creates a new Registration for an exiting (previously published) name.
470 * @throws RegistrationValidationException
472 @EventBusListenerMethod
473 public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event
) throws RegistrationValidationException
{
475 if(!event
.isStart()){
479 getView().getAddExistingNameCombobox().commit(); // update the chosen value in the datasource
480 TaxonName typifiedName
= getView().getAddExistingNameCombobox().getValue();
481 if(typifiedName
!= null){
482 boolean doReloadWorkingSet
= false;
484 doReloadWorkingSet
= registrationWorkflowService
.createRegistrationforExistingName(workingset
, typifiedName
);
487 refreshView(doReloadWorkingSet
);
488 getView().getAddExistingNameRegistrationButton().setEnabled(false);
491 logger
.error("Seletced name is NULL");
496 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
497 public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event
) {
499 if(!checkFromOwnView(event
)){
503 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
504 SpecimenTypeDesignationWorkingsetPopupEditor popup
= openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor
.class, event
);
505 popup
.setParentEditorActionContext(event
.getContext(), event
.getTarget());
506 popup
.withDeleteButton(true);
507 popup
.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event
.getRegistrationUuid(), event
.getBaseEntityRef()));
508 if(event
.hasSource()){
509 // propagate readonly state from source button to popup
510 popup
.setReadOnly(event
.getSource().isReadOnly());
513 NameTypeDesignationPopupEditor popup
= openPopupEditor(NameTypeDesignationPopupEditor
.class, event
);
514 popup
.setParentEditorActionContext(event
.getContext(), event
.getTarget());
515 popup
.withDeleteButton(true);
516 popup
.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event
.getRegistrationUuid(), event
.getBaseEntityRef()));
518 popup
.getCitationCombobox().setEnabled(false);
519 popup
.getTypifiedNamesComboboxSelect().setEnabled(false);
521 if(event
.hasSource()){
522 // propagate readonly state from source button to popup
523 popup
.setReadOnly(event
.getSource().isReadOnly());
525 nameTypeDesignationPopupEditorRegistrationUUIDMap
.put(popup
, event
.getRegistrationUuid());
529 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Add
.class)
530 public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event
) {
532 if(!event
.hasSource()){
536 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
537 SpecimenTypeDesignationWorkingsetPopupEditor popup
= openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor
.class, event
);
538 popup
.setParentEditorActionContext(event
.getContext(), event
.getTarget());
539 TypeDesignationWorkingsetEditorIdSet identifierSet
;
540 UUID typifiedNameUuid
;
542 RegistrationDTO registrationDTO
= workingset
.getRegistrationDTO(event
.getRegistrationUuid()).get();
543 EntityReference typifiedNameRef
= registrationDTO
.getTypifiedNameRef();
544 if(typifiedNameRef
!= null){
545 // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
546 typifiedNameUuid
= typifiedNameRef
.getUuid();
548 // case of registrations with a name in the nomenclatural act.
549 typifiedNameUuid
= registrationDTO
.getNameRef().getUuid();
552 identifierSet
= new TypeDesignationWorkingsetEditorIdSet(
553 event
.getRegistrationUuid(),
554 getView().getCitationUuid(),
557 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
));
558 popup
.loadInEditor(identifierSet
);
559 popup
.withDeleteButton(true);
560 if(event
.hasSource()){
561 // propagate readonly state from source component to popup
562 popup
.setReadOnly(event
.getSource().isReadOnly());
565 NameTypeDesignationPopupEditor popup
= openPopupEditor(NameTypeDesignationPopupEditor
.class, event
);
566 popup
.setParentEditorActionContext(event
.getContext(), event
.getTarget());
567 popup
.withDeleteButton(true);
568 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
));
569 RegistrationDTO regDto
= workingset
.getRegistrationDTO(event
.getRegistrationUuid()).get();
570 Reference citation
= regDto
.getCitation();
571 nameTypeDesignationPopupEditorRegistrationUUIDMap
.put(popup
, event
.getRegistrationUuid());
572 popup
.setBeanInstantiator(new BeanInstantiator
<NameTypeDesignation
>() {
575 public NameTypeDesignation
createNewBean() {
577 TaxonName typifiedName
= getRepo().getNameService().load(event
.getTypifiedNameUuid(), Arrays
.asList(new String
[]{"typeDesignations", "homotypicalGroup"}));
578 NameTypeDesignation nameTypeDesignation
= NameTypeDesignation
.NewInstance();
579 nameTypeDesignation
.setCitation(citation
);
580 nameTypeDesignation
.getTypifiedNames().add(typifiedName
);
581 return nameTypeDesignation
;
584 popup
.loadInEditor(null);
585 popup
.getCitationCombobox().setEnabled(false);
586 popup
.getTypifiedNamesComboboxSelect().setEnabled(false);
587 if(event
.hasSource()){
588 // propagate readonly state from source component to popup
589 popup
.setReadOnly(event
.getSource().isReadOnly());
595 * Performs final actions after a TypeDesignationEditor which has been
596 * opened to add a TypeDesignation to a Registration object which was
597 * created for an previously published name. Prior adding a typedesignation,
598 * the according Registration object is dangling, that has no association to
599 * any entity denoting an nomenclatural act which has a reference to a
600 * publication. This means that the registration object is not in the
605 * @throws RegistrationValidationException
607 @EventBusListenerMethod
608 public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event
) {
609 if(event
.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor
){
610 if(event
.getReason().equals(Reason
.SAVE
)){
611 // NOTE: adding the SpecimenTypeDesignations to the registration is done in the
612 // SpecimenTypeDesignationWorkingSetServiceImpl.save(SpecimenTypeDesignationWorkingSetDTO dto) method
614 } else if(event
.getReason().equals(Reason
.CANCEL
)){
617 } else if(event
.getPopup() instanceof NameTypeDesignationPopupEditor
){
618 if(event
.getReason().equals(Reason
.SAVE
)){
620 Registration registration
= null;
621 boolean doRefreshView
= false;
623 UUID typeDesignationUuid
= ((NameTypeDesignationPopupEditor
)event
.getPopup()).getBean().getUuid();
627 Stack
<EditorActionContext
>context
= ((AbstractPopupEditor
)event
.getPopup()).getEditorActionContext();
628 registration
= findRegistrationInContext(context
);
629 registrationWorkflowService
.addTypeDesignation(typeDesignationUuid
, registration
);
630 nameTypeDesignationPopupEditorRegistrationUUIDMap
.remove(event
.getPopup());
633 doRefreshView
= true;
636 if(registration
== null){
637 // no new registration has been created above, so there must be an existing one.
638 registration
= findRegistrationInContext(event
.getPopup());
641 // Check if the other names used in the context of the name are registered yet.
642 NameTypeDesignationPopupEditor nameEditor
= (NameTypeDesignationPopupEditor
)event
.getPopup();
643 Set
<TaxonName
> namesToCheck
= new HashSet
<>();
645 namesToCheck
.add(nameEditor
.getTypeNameField().getValue());
647 for(TaxonName name
: namesToCheck
){
649 doRefreshView
|= registrationWorkflowService
.addBlockingRegistration(name
.getUuid(), registration
) != null;
654 refreshView(doRefreshView
);
656 } else if(event
.getReason().equals(Reason
.CANCEL
)){
661 // ignore other editors
667 public void clearSession() {
668 getRepo().clearSession();
672 @EventBusListenerMethod(filter
= ShowDetailsEventEntityTypeFilter
.RegistrationWorkingSet
.class)
673 public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent
<RegistrationWorkingSet
,?
> event
) {
675 if(event
.getProperty().equals(RegistrationItem
.VALIDATION_PROBLEMS
)){
676 List
<String
> messages
= new ArrayList
<>();
677 for(RegistrationDTO dto
: workingset
.getRegistrationDTOs()){
678 dto
.getValidationProblems().forEach(m
-> messages
.add(dto
.getSummary() + ": " + m
));
680 getView().openDetailsPopup("Validation Problems", messages
);
684 @EventBusListenerMethod
685 public void onEntityChangeEvent(EntityChangeEvent event
){
687 if(workingset
== null){
690 if(Reference
.class.isAssignableFrom(event
.getEntityType())){
692 if(workingset
.getCitationUuid().equals(event
.getEntityUuid())){
693 if(event
.isRemovedType()){
694 viewEventBus
.publish(EventScope
.UI
, this, new NavigationEvent(StartRegistrationViewBean
.NAME
));
701 if(Registration
.class.isAssignableFrom(event
.getEntityType())){
702 if(workingset
.getRegistrations().stream().anyMatch(reg
-> reg
.getUuid() == event
.getEntityUuid())){
706 if(TaxonName
.class.isAssignableFrom(event
.getEntityType())){
707 if(event
.getType().equals(EntityChangeEvent
.Type
.CREATED
)){
708 Stack
<EditorActionContext
>context
= ((AbstractPopupEditor
)event
.getSourceView()).getEditorActionContext();
709 EditorActionContext rootContext
= context
.get(0);
710 if(rootContext
.getParentView().equals(getView()) && event
.getSourceView() != newNameForRegistrationPopupEditor
){
713 // create a blocking registration, the new Registration will be persisted
714 UUID taxonNameUUID
= event
.getEntityUuid();
716 if(context
.get(1).getParentView() instanceof TaxonNamePopupEditor
&& !((TaxonNamePopupEditor
)context
.get(1).getParentView()).getBean().cdmEntity().isPersited()){
717 // Oha!! The event came from a popup editor and the
718 // first popup in the context is a TaxonNameEditor with un-persisted name
719 // This is a name for a new registration which has not yet been created.
720 // It is necessary to store blocking registrations in the newNameBlockingRegistrations
721 Registration blockingRegistration
= getRepo().getRegistrationService().createRegistrationForName(taxonNameUUID
);
722 newNameBlockingRegistrations
.add(blockingRegistration
);
723 logger
.debug("Blocking registration created and memorized");
725 Registration registration
= findRegistrationInContext(context
);
726 // some new name somehow related to an existing registration
727 registrationWorkflowService
.addBlockingRegistration(taxonNameUUID
, registration
);
734 // in case of creating a new name for a registration the parent view is the TaxonNamePopupEditor
736 logger
.debug("Non blocking registration, since a new name for a new registration has been created");
739 if(workingset
.getRegistrationDTOs().stream().anyMatch(reg
->
740 reg
.getTypifiedNameRef() != null
741 && reg
.getTypifiedNameRef().getUuid().equals(event
.getEntityUuid()))){
745 if(TypeDesignationBase
.class.isAssignableFrom(event
.getEntityType())){
746 if(workingset
.getRegistrationDTOs().stream().anyMatch(
747 reg
-> reg
.typeDesignations() != null && reg
.typeDesignations().stream().anyMatch(
748 td
-> td
.getUuid() == event
.getEntityUuid()
757 public Registration
findRegistrationInContext(PopupView popupView
) {
758 Stack
<EditorActionContext
>context
= ((AbstractPopupEditor
)popupView
).getEditorActionContext();
759 return findRegistrationInContext(context
);
762 * Finds the Registration in the EditorContext stack
767 public Registration
findRegistrationInContext(Stack
<EditorActionContext
> context
) {
768 EditorActionContext rootCtx
= context
.get(0);
769 TypedEntityReference
<Registration
> regReference
= (TypedEntityReference
<Registration
>)rootCtx
.getParentEntity();
770 Optional
<RegistrationDTO
> registrationDTOOptional
= workingset
.getRegistrationDTO(regReference
.getUuid());
771 if(!registrationDTOOptional
.isPresent()){
772 logger
.error("RegistrationDTO missing in rootCtx.");
774 Registration registration
= registrationDTOOptional
.get().registration();
776 // registration = reloadRegistration(registration);
782 @EventBusListenerMethod(filter
= ShowDetailsEventEntityTypeFilter
.RegistrationDTO
.class)
783 public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent
<RegistrationDTO
, UUID
> event
) {
785 // FIXME check from own view!!!
786 if(getView() == null){
790 UUID registrationUuid
= event
.getIdentifier();
792 RegistrationDTO regDto
= workingset
.getRegistrationDTO(registrationUuid
).get();
793 if(event
.getProperty().equals(RegistrationItem
.BLOCKED_BY
)){
795 Set
<RegistrationDTO
> blockingRegs
;
796 if(regDto
.registration().isPersited()){
797 blockingRegs
= getWorkingSetService().loadBlockingRegistrations(registrationUuid
);
799 blockingRegs
= new HashSet
<RegistrationDTO
>(getWorkingSetService().makeDTOs(regDto
.registration().getBlockedBy()));
801 getView().setBlockingRegistrations(registrationUuid
, blockingRegs
);
802 } else if(event
.getProperty().equals(RegistrationItem
.VALIDATION_PROBLEMS
)){
803 getView().openDetailsPopup("Validation Problems", regDto
.getValidationProblems());
811 public ICdmEntityUuidCacher
getCache() {
819 public void addRootEntity(CdmBase entity
) {
820 rootEntities
.add(entity
);
829 public Collection
<CdmBase
> getRootEntities() {
834 public void destroy() throws Exception
{
843 public void disposeCache() {
851 public boolean canCreateNameRegistrationFor(TaxonName name
) {
852 return registrationWorkflowService
.canCreateNameRegistrationFor(workingset
, name
);
859 public boolean checkWokingsetContainsProtologe(TaxonName name
) {
860 return registrationWorkflowService
.checkWokingsetContainsProtologe(workingset
, name
);