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
.EnumSet
;
14 import java
.util
.HashSet
;
15 import java
.util
.List
;
16 import java
.util
.Objects
;
18 import java
.util
.Stack
;
19 import java
.util
.UUID
;
21 import org
.apache
.log4j
.Logger
;
22 import org
.hibernate
.Session
;
23 import org
.hibernate
.Transaction
;
24 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
25 import org
.springframework
.security
.core
.Authentication
;
26 import org
.springframework
.transaction
.TransactionStatus
;
27 import org
.vaadin
.spring
.events
.EventScope
;
28 import org
.vaadin
.spring
.events
.annotation
.EventBusListenerMethod
;
30 import com
.vaadin
.server
.SystemError
;
31 import com
.vaadin
.spring
.annotation
.SpringComponent
;
32 import com
.vaadin
.spring
.annotation
.ViewScope
;
33 import com
.vaadin
.ui
.AbstractField
;
34 import com
.vaadin
.ui
.Button
;
35 import com
.vaadin
.ui
.Label
;
36 import com
.vaadin
.ui
.UI
;
37 import com
.vaadin
.ui
.VerticalLayout
;
38 import com
.vaadin
.ui
.Window
;
40 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
41 import eu
.etaxonomy
.cdm
.api
.service
.IRegistrationService
;
42 import eu
.etaxonomy
.cdm
.api
.service
.config
.RegistrationStatusTransitions
;
43 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RegistrationDTO
;
44 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RegistrationWorkingSet
;
45 import eu
.etaxonomy
.cdm
.api
.service
.exception
.RegistrationValidationException
;
46 import eu
.etaxonomy
.cdm
.api
.service
.idminter
.IdentifierMinter
.Identifier
;
47 import eu
.etaxonomy
.cdm
.api
.service
.idminter
.RegistrationIdentifierMinter
;
48 import eu
.etaxonomy
.cdm
.api
.service
.name
.TypeDesignationSetManager
.TypeDesignationWorkingSetType
;
49 import eu
.etaxonomy
.cdm
.api
.service
.registration
.IRegistrationWorkingSetService
;
50 import eu
.etaxonomy
.cdm
.api
.utility
.UserHelper
;
51 import eu
.etaxonomy
.cdm
.ext
.common
.ExternalServiceException
;
52 import eu
.etaxonomy
.cdm
.ext
.registration
.messages
.IRegistrationMessageService
;
53 import eu
.etaxonomy
.cdm
.model
.common
.User
;
54 import eu
.etaxonomy
.cdm
.model
.name
.NameTypeDesignation
;
55 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
56 import eu
.etaxonomy
.cdm
.model
.name
.Registration
;
57 import eu
.etaxonomy
.cdm
.model
.name
.RegistrationStatus
;
58 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
59 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameFactory
;
60 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
61 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
62 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceType
;
63 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CRUD
;
64 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.Operation
;
65 import eu
.etaxonomy
.cdm
.ref
.EntityReference
;
66 import eu
.etaxonomy
.cdm
.ref
.TypedEntityReference
;
67 import eu
.etaxonomy
.cdm
.service
.CdmFilterablePagingProvider
;
68 import eu
.etaxonomy
.cdm
.service
.CdmStore
;
69 import eu
.etaxonomy
.cdm
.service
.UserHelperAccess
;
70 import eu
.etaxonomy
.cdm
.vaadin
.component
.CdmBeanItemContainerFactory
;
71 import eu
.etaxonomy
.cdm
.vaadin
.component
.registration
.RegistrationItem
;
72 import eu
.etaxonomy
.cdm
.vaadin
.component
.registration
.RegistrationStatusFieldInstantiator
;
73 import eu
.etaxonomy
.cdm
.vaadin
.component
.registration
.RegistrationStatusSelect
;
74 import eu
.etaxonomy
.cdm
.vaadin
.event
.AbstractEditorAction
.EditorActionContext
;
75 import eu
.etaxonomy
.cdm
.vaadin
.event
.EditorActionTypeFilter
;
76 import eu
.etaxonomy
.cdm
.vaadin
.event
.EntityChangeEvent
;
77 import eu
.etaxonomy
.cdm
.vaadin
.event
.ReferenceEditorAction
;
78 import eu
.etaxonomy
.cdm
.vaadin
.event
.RegistrationEditorAction
;
79 import eu
.etaxonomy
.cdm
.vaadin
.event
.ShowDetailsEvent
;
80 import eu
.etaxonomy
.cdm
.vaadin
.event
.ShowDetailsEventEntityTypeFilter
;
81 import eu
.etaxonomy
.cdm
.vaadin
.event
.TaxonNameEditorAction
;
82 import eu
.etaxonomy
.cdm
.vaadin
.event
.TypeDesignationWorkingsetEditorAction
;
83 import eu
.etaxonomy
.cdm
.vaadin
.event
.registration
.RegistrationWorkingsetAction
;
84 import eu
.etaxonomy
.cdm
.vaadin
.permission
.RegistrationCuratorRoleProbe
;
85 import eu
.etaxonomy
.cdm
.vaadin
.theme
.EditValoTheme
;
86 import eu
.etaxonomy
.cdm
.vaadin
.ui
.RegistrationUIDefaults
;
87 import eu
.etaxonomy
.cdm
.vaadin
.util
.CdmTitleCacheCaptionGenerator
;
88 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.NameTypeDesignationPopupEditor
;
89 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.SpecimenTypeDesignationWorkingsetPopupEditor
;
90 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNamePopupEditor
;
91 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNamePopupEditorMode
;
92 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNamePopupEditorView
;
93 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TypeDesignationWorkingsetEditorIdSet
;
94 import eu
.etaxonomy
.cdm
.vaadin
.view
.reference
.ReferencePopupEditor
;
95 import eu
.etaxonomy
.vaadin
.mvp
.AbstractPopupEditor
;
96 import eu
.etaxonomy
.vaadin
.mvp
.AbstractPresenter
;
97 import eu
.etaxonomy
.vaadin
.mvp
.AbstractView
;
98 import eu
.etaxonomy
.vaadin
.mvp
.BeanInstantiator
;
99 import eu
.etaxonomy
.vaadin
.ui
.navigation
.NavigationEvent
;
100 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
;
101 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
.Reason
;
104 * @author a.kohlbecker
110 public class RegistrationWorkingsetPresenter
extends AbstractPresenter
<RegistrationWorkingsetView
> {
112 private static final Logger logger
= Logger
.getLogger(RegistrationWorkingsetPresenter
.class);
114 private static final List
<String
> REGISTRATION_INIT_STRATEGY
= Arrays
.asList(
117 "name.combinationAuthorship",
118 "name.exCombinationAuthorship",
119 "name.basionymAuthorship",
120 "name.exBasionymAuthorship"
123 private static final long serialVersionUID
= 1L;
126 private IRegistrationWorkingSetService regWorkingSetService
;
129 private RegistrationIdentifierMinter minter
;
132 private IRegistrationMessageService messageService
;
135 * @return the regWorkingSetService
137 public IRegistrationWorkingSetService
getWorkingSetService() {
138 return regWorkingSetService
;
141 private RegistrationWorkingSet workingset
;
143 private TaxonName newTaxonNameForRegistration
= null;
145 private RegistrationDTO newRegistrationDTOWithExistingName
;
147 private RegistrationDTO newNameTypeDesignationTarget
;
153 public RegistrationWorkingsetPresenter() {
157 * Always create a new Store
161 protected CdmStore
<Registration
, IRegistrationService
> getRegistrationStore(){
162 return new CdmStore
<Registration
, IRegistrationService
>(getRepo(), getRepo().getRegistrationService());
166 * Always create a new Store
170 protected CdmStore
<TaxonName
, INameService
> getTaxonNameStore(){
171 return new CdmStore
<TaxonName
, INameService
>(getRepo(), getRepo().getNameService());
177 * <li>if there is NOT any registration for this name created in the current registration system</li>
178 * <li>Checks if the name belongs to the current workingset</li>
180 * If both checks are successful the method returns <code>true</code>.
182 public boolean canCreateNameRegistrationFor(TaxonName name
) {
183 return !checkRegistrationExistsFor(name
) && checkWokingsetContainsProtologe(name
);
190 public boolean checkWokingsetContainsProtologe(TaxonName name
) {
191 Reference nomRef
= name
.getNomenclaturalReference();
192 UUID citationUuid
= workingset
.getCitationUuid();
194 return nomRef
!= null && (
196 nomRef
.getUuid().equals(citationUuid
) ||
197 // nomref.inreference matches
198 (nomRef
.getType() != null && nomRef
.getType() == ReferenceType
.Section
&& nomRef
.getInReference() != null && nomRef
.getInReference().getUuid().equals(citationUuid
))
206 public boolean checkRegistrationExistsFor(TaxonName name
) {
208 for(Registration reg
: name
.getRegistrations()){
209 if(minter
.isFromOwnRegistration(reg
.getIdentifier())){
222 protected Registration
createNewRegistrationForName(UUID taxonNameUuid
) {
223 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
224 // move into RegistrationWorkflowStateMachine
225 TransactionStatus txStatus
= getRepo().startTransaction();
227 Identifier
<String
> identifiers
= minter
.mint();
228 if(identifiers
.getIdentifier() == null){
229 throw new RuntimeException("RegistrationIdentifierMinter configuration incomplete.");
231 Registration reg
= Registration
.NewInstance(
232 identifiers
.getIdentifier(),
233 identifiers
.getLocalId(),
234 taxonNameUuid
!= null ?
getRepo().getNameService().load(taxonNameUuid
, Arrays
.asList("nomenclaturalReference.inReference")) : null,
236 Authentication authentication
= currentSecurityContext().getAuthentication();
237 reg
.setSubmitter((User
)authentication
.getPrincipal());
238 EntityChangeEvent event
= getRegistrationStore().saveBean(reg
, (AbstractView
) getView());
239 UserHelperAccess
.userHelper().createAuthorityForCurrentUser(Registration
.class, event
.getEntityUuid(), Operation
.UPDATE
, RegistrationStatus
.PREPARATION
.name());
240 getRepo().commitTransaction(txStatus
);
241 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
242 return getRepo().getRegistrationService().load(event
.getEntityUuid(), Arrays
.asList(new String
[]{"blockedBy"}));
246 * @param doReload TODO
249 protected void refreshView(boolean doReload
) {
250 if(workingset
== null){
251 return; // nothing to do
254 loadWorkingSet(workingset
.getCitationUuid());
263 public void handleViewEntered() {
264 super.handleViewEntered();
265 // TODO currently cannot specify type more precisely, see AbstractSelect
266 // FIXME externalize into class file!!!!!!!!!!!!
267 getView().setStatusComponentInstantiator(new RegistrationStatusFieldInstantiator
<Object
>(){
269 private static final long serialVersionUID
= 7099181280977511048L;
272 public AbstractField
<Object
> create(RegistrationDTO regDto
) {
274 CdmBeanItemContainerFactory selectFieldFactory
= new CdmBeanItemContainerFactory(getRepo());
275 // submitters have GrantedAuthorities like REGISTRATION(PREPARATION).[UPDATE]{ab4459eb-3b96-40ba-bfaa-36915107d59e}
276 UserHelper userHelper
= UserHelperAccess
.userHelper();
277 Set
<RegistrationStatus
> availableStatus
= new HashSet
<>();
279 boolean canChangeStatus
= userHelper
.userHasPermission(regDto
.registration(), CRUD
.UPDATE
);
280 availableStatus
.add(regDto
.getStatus());
282 if(userHelper
.userIsAdmin()){
283 availableStatus
.addAll(Arrays
.asList(RegistrationStatus
.values()));
285 availableStatus
.addAll(RegistrationStatusTransitions
.possibleTransitions(regDto
.getStatus()));
289 RegistrationStatusSelect select
= new RegistrationStatusSelect(null, selectFieldFactory
.buildBeanItemContainer(
290 RegistrationStatus
.class,
291 availableStatus
.toArray(new RegistrationStatus
[availableStatus
.size()]))
293 select
.addValueChangeListener(e
-> saveRegistrationStatusChange(regDto
.getUuid(), e
.getProperty().getValue()));
294 select
.setEnabled(canChangeStatus
);
295 select
.setNullSelectionAllowed(false);
301 loadWorkingSet(getView().getCitationUuid());
306 private void applyWorkingset(){
307 getView().setWorkingset(workingset
);
308 // PagingProviders and CacheGenerator for the existingNameCombobox
309 activateComboboxes();
310 // update the messages
317 protected void activateComboboxes() {
318 CdmFilterablePagingProvider
<TaxonName
, TaxonName
> pagingProvider
= new CdmFilterablePagingProvider
<TaxonName
, TaxonName
>(
319 getRepo().getNameService());
320 pagingProvider
.setInitStrategy(Arrays
.asList("registrations", "nomenclaturalReference"));
321 CdmTitleCacheCaptionGenerator
<TaxonName
> titleCacheGenerator
= new CdmTitleCacheCaptionGenerator
<TaxonName
>();
322 getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenerator
);
323 getView().getAddExistingNameCombobox().loadFrom(pagingProvider
, pagingProvider
, pagingProvider
.getPageSize());
329 protected void updateMessages() {
330 User user
= UserHelperAccess
.userHelper().user();
331 for (UUID registrationUuid
: getView().getRegistrationItemMap().keySet()) {
332 Button messageButton
= getView().getRegistrationItemMap().get(registrationUuid
).regItemButtons
.getMessagesButton();
334 RegistrationDTO regDto
= workingset
.getRegistrationDTO(registrationUuid
).get();
336 int messageCount
= messageService
.countActiveMessagesFor(regDto
.registration(), user
);
338 boolean activeMessages
= messageCount
> 0;
339 boolean currentUserIsSubmitter
= regDto
.getSubmitterUserName() != null && regDto
.getSubmitterUserName().equals(UserHelperAccess
.userHelper().userName());
340 boolean currentUserIsCurator
= UserHelperAccess
.userHelper().userIs(new RegistrationCuratorRoleProbe());
341 messageButton
.setEnabled(false);
342 if(currentUserIsCurator
){
343 if(currentUserIsSubmitter
){
344 messageButton
.setDescription("No point sending messages to your self.");
346 messageButton
.setEnabled(true);
347 messageButton
.setDescription("Open the messages dialog.");
350 messageButton
.setDescription("Sorry, only a curator can start a conversation.");
353 messageButton
.setEnabled(true);
354 messageButton
.addStyleName(EditValoTheme
.BUTTON_HIGHLITE
);
355 String who
= currentUserIsSubmitter ?
"curator" : "submitter";
356 messageButton
.setDescription("The " + who
+ " is looking forward to your reply.");
359 } catch (ExternalServiceException e
) {
360 messageButton
.setComponentError(new SystemError(e
.getMessage(), e
));
369 protected void loadWorkingSet(UUID referenceUuid
) {
371 workingset
= getWorkingSetService().loadWorkingSetByReferenceUuid(referenceUuid
, true);
372 } catch (RegistrationValidationException error
) {
374 Window errorDialog
= new Window("Validation Error");
375 errorDialog
.setModal(true);
376 VerticalLayout subContent
= new VerticalLayout();
377 subContent
.setMargin(true);
378 errorDialog
.setContent(subContent
);
379 subContent
.addComponent(new Label(error
.getMessage()));
380 UI
.getCurrent().addWindow(errorDialog
);
382 if(workingset
== null || workingset
.getCitationUuid() == null){
383 Reference citation
= getRepo().getReferenceService().find(referenceUuid
);
384 workingset
= new RegistrationWorkingSet(citation
);
388 private void saveRegistrationStatusChange(UUID uuid
, Object value
) {
389 Registration reg
= getRepo().getRegistrationService().load(uuid
);
390 if(value
!= null && value
instanceof RegistrationStatus
){
391 if(!Objects
.equals(value
, reg
.getStatus())){
392 reg
.setStatus((RegistrationStatus
)value
);
393 getRegistrationStore().saveBean(reg
, (AbstractView
)getView());
397 // only log here as error
398 logger
.error("Ivalid attempt to set RegistrationStatus to " + Objects
.toString(value
.toString(), "NULL"));
403 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Add
.class)
404 public void onReferenceEditorActionAdd(ReferenceEditorAction event
) {
406 if(!checkFromOwnView(event
)){
410 ReferencePopupEditor popup
= openPopupEditor(ReferencePopupEditor
.class, event
);
411 popup
.withReferenceTypes(RegistrationUIDefaults
.PRINTPUB_REFERENCE_TYPES
);
412 popup
.loadInEditor(null);
415 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
416 public void onReferenceEditorActionEdit(ReferenceEditorAction event
) {
418 if(!checkFromOwnView(event
)){
421 ReferencePopupEditor popup
= openPopupEditor(ReferencePopupEditor
.class, event
);
422 popup
.withReferenceTypes(RegistrationUIDefaults
.PRINTPUB_REFERENCE_TYPES
);
423 popup
.withDeleteButton(true);
424 popup
.loadInEditor(event
.getEntityUuid());
427 @EventBusListenerMethod
428 public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
429 if(event
.getPopup() instanceof ReferencePopupEditor
){
430 if(event
.getReason().equals(Reason
.SAVE
)){
436 @EventBusListenerMethod
437 public void onDoneWithSpecimenTypeDesignationWorkingsetPopupEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
438 if(event
.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor
){
439 if(event
.getReason().equals(Reason
.SAVE
)){
445 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
446 public void onRegistrationEditorAction(RegistrationEditorAction event
) {
448 if(!checkFromOwnView(event
)){
452 RegistrationPopupEditor popup
= openPopupEditor(RegistrationPopupEditor
.class, event
);
453 popup
.loadInEditor(event
.getEntityUuid());
456 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
457 public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event
) {
459 if(!checkFromOwnView(event
)){
463 TaxonNamePopupEditor popup
= openPopupEditor(TaxonNamePopupEditor
.class, event
);
464 popup
.setParentEditorActionContext(event
.getContext());
465 popup
.withDeleteButton(true);
466 configureTaxonNameEditor(popup
);
467 popup
.loadInEditor(event
.getEntityUuid());
468 if(event
.hasSource() && event
.getSource().isReadOnly()){
469 // avoid resetting readonly to false
470 popup
.setReadOnly(true);
476 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Add
.class)
477 public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event
) {
479 if(!checkFromOwnView(event
)){
483 newTaxonNameForRegistration
= TaxonNameFactory
.NewNameInstance(RegistrationUIDefaults
.NOMENCLATURAL_CODE
, Rank
.SPECIES());
484 newTaxonNameForRegistration
.setNomenclaturalReference(getRepo().getReferenceService().find(workingset
.getCitationUuid()));
485 EntityChangeEvent nameSaveEvent
= getTaxonNameStore().saveBean(newTaxonNameForRegistration
, (AbstractView
) getView());
486 newTaxonNameForRegistration
= getRepo().getNameService().find(nameSaveEvent
.getEntityUuid());
487 TaxonNamePopupEditor popup
= openPopupEditor(TaxonNamePopupEditor
.class, event
);
488 popup
.setParentEditorActionContext(event
.getContext());
489 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
,CRUD
.DELETE
));
490 popup
.withDeleteButton(true);
491 configureTaxonNameEditor(popup
);
492 popup
.loadInEditor(newTaxonNameForRegistration
.getUuid());
496 * TODO consider putting this into a Configurer Bean per UIScope.
497 * In the configurator bean this methods popup papamerter should be of the type
498 * AbstractPopupEditor
502 protected void configureTaxonNameEditor(TaxonNamePopupEditorView popup
) {
503 popup
.enableMode(TaxonNamePopupEditorMode
.AUTOFILL_AUTHORSHIP_DATA
);
504 popup
.enableMode(TaxonNamePopupEditorMode
.NOMENCLATURALREFERENCE_SECTION_EDITING_ONLY
);
505 popup
.enableMode(TaxonNamePopupEditorMode
.VALIDATE_AGAINST_HIGHER_NAME_PART
);
506 // popup.enableMode(TaxonNamePopupEditorMode.REQUIRE_NOMENCLATURALREFERENCE);
510 * Creates a new <code>Registration</code> for a new name that has just been edited
511 * using the <code>TaxonNamePopupEditor</code>. The new name was previously created
512 * in this presenter as <code>newTaxonNameForRegistration</code> (see {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)})
513 * and is either filled with data (<code>Reason.SAVE</code>) or it is still empty
514 * (<code>Reason.CANCEL</code>).
518 * @throws RegistrationValidationException
520 @EventBusListenerMethod
521 public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
522 if(event
.getPopup() instanceof TaxonNamePopupEditor
){
523 TransactionStatus txStatus
= getRepo().startTransaction();
524 if(event
.getReason().equals(Reason
.SAVE
)){
525 if(newTaxonNameForRegistration
!= null){
526 UUID taxonNameUuid
= newTaxonNameForRegistration
.getUuid();
527 getRepo().getSession().refresh(newTaxonNameForRegistration
);
528 Registration reg
= createNewRegistrationForName(taxonNameUuid
);
529 // reload workingset into current session
530 loadWorkingSet(workingset
.getCitationUuid());
534 } else if(event
.getReason().equals(Reason
.CANCEL
)){
535 if(newTaxonNameForRegistration
!= null){
537 getTaxonNameStore().deleteBean(newTaxonNameForRegistration
, (AbstractView
) getView());
540 getRepo().commitTransaction(txStatus
);
541 newTaxonNameForRegistration
= null;
547 * Creates a new Registration for an exiting (previously published name).
550 * @throws RegistrationValidationException
552 @EventBusListenerMethod
553 public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event
) throws RegistrationValidationException
{
555 if(!event
.isStart()){
559 getView().getAddExistingNameCombobox().commit(); // update the chosen value in the datasource
560 TaxonName typifiedName
= getView().getAddExistingNameCombobox().getValue();
561 if(typifiedName
!= null){
562 boolean reloadWorkingSet
= false;
563 Reference citation
= getRepo().getReferenceService().find(workingset
.getCitationUuid());
564 // here we completely ignore the ExistingNameRegistrationType since the user should not have the choice
565 // to create a typification only registration in the working (publication) set which contains
566 // the protologe. This is known from the nomenclatural reference.
567 if(canCreateNameRegistrationFor(typifiedName
)){
568 // the citation which is the base for workingset contains the protologe of the name and the name has not
569 // been registered before:
570 // create a registration for the name and the first typifications
571 Registration newRegistrationWithExistingName
= createNewRegistrationForName(typifiedName
.getUuid());
572 newRegistrationDTOWithExistingName
= new RegistrationDTO(newRegistrationWithExistingName
, typifiedName
, citation
);
573 reloadWorkingSet
= true;
575 if(!checkWokingsetContainsProtologe(typifiedName
)){
576 // create a typification only registration
577 Registration typificationOnlyRegistration
= createNewRegistrationForName(null);
578 if(!checkRegistrationExistsFor(typifiedName
)){
579 // oops, yet no registration for this name, so we create it as blocking registration:
580 Registration blockingNameRegistration
= createNewRegistrationForName(typifiedName
.getUuid());
581 typificationOnlyRegistration
.getBlockedBy().add(blockingNameRegistration
);
583 newRegistrationDTOWithExistingName
= new RegistrationDTO(typificationOnlyRegistration
, typifiedName
, citation
);
586 workingset
.add(newRegistrationDTOWithExistingName
);
587 // tell the view to update the workingset
588 refreshView(reloadWorkingSet
);
589 getView().getAddExistingNameRegistrationButton().setEnabled(false);
590 if(newRegistrationDTOWithExistingName
.registration().getName() == null){
591 getView().getAddExistingNameCombobox().setEnabled(false);
592 getView().getAddNewNameRegistrationButton().setEnabled(false);
593 getView().getAddNewNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
594 getView().getAddExistingNameCombobox().setDescription("You first need to add a type designation to the previously created registration.");
595 getView().getAddExistingNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
598 logger
.error("Seletced name is NULL");
604 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Edit
.class)
605 public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event
) {
607 if(!checkFromOwnView(event
)){
611 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
612 SpecimenTypeDesignationWorkingsetPopupEditor popup
= openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor
.class, event
);
613 popup
.setParentEditorActionContext(event
.getContext());
614 popup
.withDeleteButton(true);
615 popup
.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event
.getRegistrationUuid(), event
.getBaseEntityRef()));
616 if(event
.hasSource()){
617 // propagate readonly state from source button to popup
618 popup
.setReadOnly(event
.getSource().isReadOnly());
621 NameTypeDesignationPopupEditor popup
= openPopupEditor(NameTypeDesignationPopupEditor
.class, event
);
622 popup
.setParentEditorActionContext(event
.getContext());
623 popup
.withDeleteButton(true);
624 popup
.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event
.getRegistrationUuid(), event
.getBaseEntityRef()));
626 popup
.getCitationCombobox().setEnabled(false);
627 popup
.getTypifiedNamesComboboxSelect().setEnabled(false);
629 if(event
.hasSource()){
630 // propagate readonly state from source button to popup
631 popup
.setReadOnly(event
.getSource().isReadOnly());
633 newNameTypeDesignationTarget
= workingset
.getRegistrationDTO(event
.getRegistrationUuid()).get();
637 @EventBusListenerMethod(filter
= EditorActionTypeFilter
.Add
.class)
638 public void onTypeDesignationWorkingsetAdd(TypeDesignationWorkingsetEditorAction event
) {
640 if(!event
.hasSource()){
644 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
645 SpecimenTypeDesignationWorkingsetPopupEditor popup
= openPopupEditor(SpecimenTypeDesignationWorkingsetPopupEditor
.class, event
);
646 popup
.setParentEditorActionContext(event
.getContext());
647 TypeDesignationWorkingsetEditorIdSet identifierSet
;
648 UUID typifiedNameUuid
;
649 if(newRegistrationDTOWithExistingName
!= null){
650 typifiedNameUuid
= newRegistrationDTOWithExistingName
.getTypifiedNameRef().getUuid();
652 RegistrationDTO registrationDTO
= workingset
.getRegistrationDTO(event
.getRegistrationUuid()).get();
653 EntityReference typifiedNameRef
= registrationDTO
.getTypifiedNameRef();
654 if(typifiedNameRef
!= null){
655 // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
656 typifiedNameUuid
= typifiedNameRef
.getUuid();
658 // case of registrations with a name in the nomenclatural act.
659 typifiedNameUuid
= registrationDTO
.getNameRef().getUuid();
662 identifierSet
= new TypeDesignationWorkingsetEditorIdSet(
663 event
.getRegistrationUuid(),
664 getView().getCitationUuid(),
667 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
));
668 popup
.loadInEditor(identifierSet
);
669 popup
.withDeleteButton(true);
670 if(event
.hasSource()){
671 // propagate readonly state from source component to popup
672 popup
.setReadOnly(event
.getSource().isReadOnly());
675 NameTypeDesignationPopupEditor popup
= openPopupEditor(NameTypeDesignationPopupEditor
.class, event
);
676 popup
.setParentEditorActionContext(event
.getContext());
677 popup
.withDeleteButton(true);
678 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
));
679 newNameTypeDesignationTarget
= workingset
.getRegistrationDTO(event
.getRegistrationUuid()).get();
680 popup
.setBeanInstantiator(new BeanInstantiator
<NameTypeDesignation
>() {
683 public NameTypeDesignation
createNewBean() {
685 TaxonName typifiedName
= getRepo().getNameService().load(event
.getTypifiedNameUuid(), Arrays
.asList(new String
[]{"typeDesignations", "homotypicalGroup"}));
686 NameTypeDesignation nameTypeDesignation
= NameTypeDesignation
.NewInstance();
687 nameTypeDesignation
.setCitation(newNameTypeDesignationTarget
.getCitation());
688 nameTypeDesignation
.getTypifiedNames().add(typifiedName
);
689 return nameTypeDesignation
;
692 popup
.loadInEditor(null);
693 popup
.getCitationCombobox().setEnabled(false);
694 popup
.getTypifiedNamesComboboxSelect().setEnabled(false);
695 if(event
.hasSource()){
696 // propagate readonly state from source component to popup
697 popup
.setReadOnly(event
.getSource().isReadOnly());
703 * Performs final actions after a TypeDesignationEditor which has been
704 * opened to add a TypeDesignation to a Registration object which was
705 * created for an previously published name. Prior adding a typedesignation,
706 * the according Registration object is dangling, that has no association to
707 * any entity denoting an nomenclatural act which has a reference to a
708 * publication. This means that the registration object is not in the
713 * @throws RegistrationValidationException
715 @EventBusListenerMethod
716 public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
717 if(event
.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor
){
718 if(event
.getReason().equals(Reason
.SAVE
)){
720 } else if(event
.getReason().equals(Reason
.CANCEL
)){
723 newRegistrationDTOWithExistingName
= null;
724 } else if(event
.getPopup() instanceof NameTypeDesignationPopupEditor
){
725 if(event
.getReason().equals(Reason
.SAVE
)){
726 UUID uuid
= ((NameTypeDesignationPopupEditor
)event
.getPopup()).getBean().getUuid();
728 Session session
= getRepo().getSessionFactory().openSession();
729 Transaction txstate
= session
.beginTransaction();
730 TypeDesignationBase
<?
> nameTypeDesignation
= getRepo().getNameService().loadTypeDesignation(uuid
, Arrays
.asList(""));
731 // only load the typeDesignations with the registration so that the typified name can not be twice in the session
732 // otherwise multiple representation problems might occur
733 Registration registration
= getRepo().getRegistrationService().load(newNameTypeDesignationTarget
.getUuid(), Arrays
.asList("typeDesignations"));
734 registration
.getTypeDesignations().add(nameTypeDesignation
);
735 session
.merge(registration
);
740 } else if(event
.getReason().equals(Reason
.CANCEL
)){
743 newNameTypeDesignationTarget
= null;
745 // ignore other editors
749 @EventBusListenerMethod(filter
= ShowDetailsEventEntityTypeFilter
.RegistrationWorkingSet
.class)
750 public void onShowDetailsEventForRegistrationWorkingSet(ShowDetailsEvent
<RegistrationWorkingSet
,?
> event
) {
752 if(event
.getProperty().equals(RegistrationItem
.VALIDATION_PROBLEMS
)){
753 List
<String
> messages
= new ArrayList
<>();
754 for(RegistrationDTO dto
: workingset
.getRegistrationDTOs()){
755 dto
.getValidationProblems().forEach(m
-> messages
.add(dto
.getSummary() + ": " + m
));
757 getView().openDetailsPopup("Validation Problems", messages
);
761 @EventBusListenerMethod
762 public void onEntityChangeEvent(EntityChangeEvent event
){
764 if(workingset
== null){
767 if(Reference
.class.isAssignableFrom(event
.getEntityType())){
769 if(workingset
.getCitationUuid().equals(event
.getEntityUuid())){
770 if(event
.isRemovedType()){
771 viewEventBus
.publish(EventScope
.UI
, this, new NavigationEvent(StartRegistrationViewBean
.NAME
));
778 if(Registration
.class.isAssignableFrom(event
.getEntityType())){
779 if(workingset
.getRegistrations().stream().anyMatch(reg
-> reg
.getUuid() == event
.getEntityUuid())){
783 if(TaxonName
.class.isAssignableFrom(event
.getEntityType()) && isFromOwnView(event
)){
784 if(event
.getType().equals(EntityChangeEvent
.Type
.CREATED
)){
785 // new name! create a blocking registration
786 Stack
<EditorActionContext
>context
= ((AbstractPopupEditor
)event
.getSourceView()).getEditorActionContext();
787 EditorActionContext rootContext
= context
.get(0);
788 if(rootContext
.getParentView().equals(getView())){
789 Registration blockingRegistration
= createNewRegistrationForName(event
.getEntityUuid());
790 TypedEntityReference
<Registration
> regReference
= (TypedEntityReference
<Registration
>)rootContext
.getParentEntity();
791 Registration registration
= getRepo().getRegistrationService().load(regReference
.getUuid(), REGISTRATION_INIT_STRATEGY
);
792 registration
.getBlockedBy().add(blockingRegistration
);
793 getRepo().getRegistrationService().saveOrUpdate(registration
);
794 logger
.debug("Blocking registration created");
796 logger
.debug("Non blocking registration, since a new name for a new registration has been created");
799 if(workingset
.getRegistrationDTOs().stream().anyMatch(reg
->
800 reg
.getTypifiedNameRef() != null
801 && reg
.getTypifiedNameRef().getUuid().equals(event
.getEntityUuid()))){
805 if(TypeDesignationBase
.class.isAssignableFrom(event
.getEntityType())){
806 if(workingset
.getRegistrationDTOs().stream().anyMatch(
807 reg
-> reg
.typeDesignations() != null && reg
.typeDesignations().stream().anyMatch(
808 td
-> td
.getUuid() == event
.getEntityUuid()
818 @EventBusListenerMethod(filter
= ShowDetailsEventEntityTypeFilter
.RegistrationDTO
.class)
819 public void onShowDetailsEventForRegistrationDTO(ShowDetailsEvent
<RegistrationDTO
, UUID
> event
) {
821 // FIXME check from own view!!!
822 if(getView() == null){
826 UUID registrationUuid
= event
.getIdentifier();
828 RegistrationDTO regDto
= getWorkingSetService().loadDtoByUuid(registrationUuid
);
829 if(event
.getProperty().equals(RegistrationItem
.BLOCKED_BY
)){
831 Set
<RegistrationDTO
> blockingRegs
= getWorkingSetService().loadBlockingRegistrations(registrationUuid
);
832 getView().setBlockingRegistrations(registrationUuid
, blockingRegs
);
833 } else if(event
.getProperty().equals(RegistrationItem
.MESSAGES
)){
835 RegistrationMessagesPopup popup
= openPopupEditor(RegistrationMessagesPopup
.class, null);
836 popup
.loadMessagesFor(regDto
.getUuid());
838 } else if(event
.getProperty().equals(RegistrationItem
.VALIDATION_PROBLEMS
)){
839 getView().openDetailsPopup("Validation Problems", regDto
.getValidationProblems());