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
.EnumSet
;
13 import java
.util
.List
;
15 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
16 import org
.springframework
.context
.event
.EventListener
;
17 import org
.springframework
.security
.core
.Authentication
;
18 import org
.springframework
.transaction
.TransactionStatus
;
20 import com
.vaadin
.spring
.annotation
.SpringComponent
;
21 import com
.vaadin
.spring
.annotation
.ViewScope
;
22 import com
.vaadin
.ui
.Label
;
23 import com
.vaadin
.ui
.UI
;
24 import com
.vaadin
.ui
.VerticalLayout
;
25 import com
.vaadin
.ui
.Window
;
27 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
28 import eu
.etaxonomy
.cdm
.api
.service
.IRegistrationService
;
29 import eu
.etaxonomy
.cdm
.api
.service
.idminter
.IdentifierMinter
.Identifier
;
30 import eu
.etaxonomy
.cdm
.api
.service
.idminter
.RegistrationIdentifierMinter
;
31 import eu
.etaxonomy
.cdm
.model
.common
.User
;
32 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
33 import eu
.etaxonomy
.cdm
.model
.name
.Registration
;
34 import eu
.etaxonomy
.cdm
.model
.name
.RegistrationStatus
;
35 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
36 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameFactory
;
37 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
38 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
39 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CRUD
;
40 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.Operation
;
41 import eu
.etaxonomy
.cdm
.service
.CdmFilterablePagingProvider
;
42 import eu
.etaxonomy
.cdm
.service
.CdmStore
;
43 import eu
.etaxonomy
.cdm
.service
.IRegistrationWorkingSetService
;
44 import eu
.etaxonomy
.cdm
.vaadin
.event
.EntityChangeEvent
;
45 import eu
.etaxonomy
.cdm
.vaadin
.event
.ReferenceEditorAction
;
46 import eu
.etaxonomy
.cdm
.vaadin
.event
.RegistrationEditorAction
;
47 import eu
.etaxonomy
.cdm
.vaadin
.event
.ShowDetailsEvent
;
48 import eu
.etaxonomy
.cdm
.vaadin
.event
.TaxonNameEditorAction
;
49 import eu
.etaxonomy
.cdm
.vaadin
.event
.TypeDesignationWorkingsetEditorAction
;
50 import eu
.etaxonomy
.cdm
.vaadin
.event
.registration
.RegistrationWorkingsetAction
;
51 import eu
.etaxonomy
.cdm
.vaadin
.model
.EntityReference
;
52 import eu
.etaxonomy
.cdm
.vaadin
.model
.registration
.RegistrationWorkingSet
;
53 import eu
.etaxonomy
.cdm
.vaadin
.security
.UserHelper
;
54 import eu
.etaxonomy
.cdm
.vaadin
.ui
.RegistrationUIDefaults
;
55 import eu
.etaxonomy
.cdm
.vaadin
.util
.CdmTitleCacheCaptionGenerator
;
56 import eu
.etaxonomy
.cdm
.vaadin
.util
.converter
.TypeDesignationSetManager
.TypeDesignationWorkingSetType
;
57 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.SpecimenTypeDesignationWorkingsetPopupEditor
;
58 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNamePopupEditor
;
59 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNamePopupEditorMode
;
60 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TypeDesignationWorkingsetEditorIdSet
;
61 import eu
.etaxonomy
.cdm
.vaadin
.view
.reference
.ReferencePopupEditor
;
62 import eu
.etaxonomy
.vaadin
.mvp
.AbstractPresenter
;
63 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
;
64 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
.Reason
;
67 * @author a.kohlbecker
73 public class RegistrationWorkingsetPresenter
extends AbstractPresenter
<RegistrationWorkingsetView
> {
75 private static final long serialVersionUID
= 1L;
78 private IRegistrationWorkingSetService workingSetService
;
81 private RegistrationIdentifierMinter minter
;
84 * @return the workingSetService
86 public IRegistrationWorkingSetService
getWorkingSetService() {
87 return workingSetService
;
90 private RegistrationWorkingSet workingset
;
92 private TaxonName newTaxonNameForRegistration
= null;
94 private RegistrationDTO newRegistrationDTOWithExistingName
;
100 public RegistrationWorkingsetPresenter() {
105 * Always create a new Store
109 protected CdmStore
<Registration
, IRegistrationService
> getRegistrationStore(){
110 return new CdmStore
<Registration
, IRegistrationService
>(getRepo(), getRepo().getRegistrationService());
114 * Always create a new Store
118 protected CdmStore
<TaxonName
, INameService
> getTaxonNameStore(){
119 return new CdmStore
<TaxonName
, INameService
>(getRepo(), getRepo().getNameService());
127 protected Registration
createNewRegistrationForName(Integer taxonNameId
) {
128 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
129 // move into RegistrationWorkflowStateMachine
130 TransactionStatus txStatus
= getRepo().startTransaction();
131 long identifier
= System
.currentTimeMillis();
133 Identifier
<String
> identifiers
= minter
.mint();
134 if(identifiers
.getIdentifier() == null){
135 throw new RuntimeException("RegistrationIdentifierMinter configuration incomplete.");
137 Registration reg
= Registration
.NewInstance(
138 identifiers
.getIdentifier(),
139 identifiers
.getLocalId(),
140 taxonNameId
!= null ?
getRepo().getNameService().find(taxonNameId
) : null,
142 Authentication authentication
= currentSecurityContext().getAuthentication();
143 reg
.setSubmitter((User
)authentication
.getPrincipal());
144 EntityChangeEvent event
= getRegistrationStore().saveBean(reg
);
145 UserHelper
.fromSession().createAuthorityForCurrentUser(Registration
.class, event
.getEntityId(), Operation
.UPDATE
, RegistrationStatus
.PREPARATION
.name());
146 getRepo().commitTransaction(txStatus
);
147 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
148 return getRepo().getRegistrationService().find(event
.getEntityId());
153 * @param doReload TODO
156 protected void refreshView(boolean doReload
) {
158 loadWorkingSet(workingset
.getCitationId());
160 getView().setWorkingset(workingset
);
168 public void handleViewEntered() {
170 super.handleViewEntered();
172 loadWorkingSet(getView().getCitationID());
173 getView().setWorkingset(workingset
);
175 CdmFilterablePagingProvider
<TaxonName
, TaxonName
> pagingProvider
= new CdmFilterablePagingProvider
<TaxonName
, TaxonName
>(
176 getRepo().getNameService());
177 CdmTitleCacheCaptionGenerator
<TaxonName
> titleCacheGenrator
= new CdmTitleCacheCaptionGenerator
<TaxonName
>();
178 getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenrator
);
179 getView().getAddExistingNameCombobox().loadFrom(pagingProvider
, pagingProvider
, pagingProvider
.getPageSize());
186 protected void loadWorkingSet(Integer referenceID
) {
188 workingset
= getWorkingSetService().loadWorkingSetByReferenceID(referenceID
);
189 } catch (RegistrationValidationException error
) {
191 Window errorDialog
= new Window("Validation Error");
192 errorDialog
.setModal(true);
193 VerticalLayout subContent
= new VerticalLayout();
194 subContent
.setMargin(true);
195 errorDialog
.setContent(subContent
);
196 subContent
.addComponent(new Label(error
.getMessage()));
197 UI
.getCurrent().addWindow(errorDialog
);
199 if(workingset
== null || workingset
.getCitationId() == null){
200 Reference citation
= getRepo().getReferenceService().find(referenceID
);
201 workingset
= new RegistrationWorkingSet(citation
);
205 @EventListener(condition
= "#event.type == T(eu.etaxonomy.vaadin.event.EditorActionType).ADD")
206 public void onReferenceEditorActionAdd(ReferenceEditorAction event
) {
208 if(!checkFromOwnView(event
)){
212 ReferencePopupEditor popup
= getNavigationManager().showInPopup(ReferencePopupEditor
.class);
213 popup
.withReferenceTypes(RegistrationUIDefaults
.PRINTPUB_REFERENCE_TYPES
);
214 popup
.loadInEditor(null);
217 @EventListener(condition
= "#event.type == T(eu.etaxonomy.vaadin.event.EditorActionType).EDIT")
218 public void onReferenceEditorActionEdit(ReferenceEditorAction event
) {
220 if(!checkFromOwnView(event
)){
223 ReferencePopupEditor popup
= getNavigationManager().showInPopup(ReferencePopupEditor
.class);
224 popup
.withReferenceTypes(RegistrationUIDefaults
.PRINTPUB_REFERENCE_TYPES
);
225 popup
.withDeleteButton(true);
226 popup
.loadInEditor(event
.getEntityId());
230 public void onDoneWithReferencePopupEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
231 if(event
.getPopup() instanceof ReferencePopupEditor
){
232 if(event
.getReason().equals(Reason
.SAVE
)){
239 public void onDoneWithSpecimenTypeDesignationWorkingsetPopupEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
240 if(event
.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor
){
241 if(event
.getReason().equals(Reason
.SAVE
)){
247 @EventListener(condition
= "#event.type == T(eu.etaxonomy.vaadin.event.EditorActionType).EDIT")
248 public void onRegistrationEditorAction(RegistrationEditorAction event
) {
250 if(!checkFromOwnView(event
)){
254 RegistrationPopupEditor popup
= getNavigationManager().showInPopup(RegistrationPopupEditor
.class);
255 popup
.loadInEditor(event
.getEntityId());
258 @EventListener(condition
= "#event.type == T(eu.etaxonomy.vaadin.event.EditorActionType).EDIT")
259 public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event
) {
261 if(!checkFromOwnView(event
)){
265 TaxonNamePopupEditor popup
= getNavigationManager().showInPopup(TaxonNamePopupEditor
.class);
266 popup
.withDeleteButton(true);
267 configureTaxonNameEditor(popup
);
268 popup
.loadInEditor(event
.getEntityId());
269 if(event
.getSourceComponent() != null){
270 popup
.setReadOnly(event
.getSourceComponent().isReadOnly());
276 @EventListener(condition
= "#event.type == T(eu.etaxonomy.vaadin.event.EditorActionType).ADD")
277 public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event
) {
279 if(!checkFromOwnView(event
)){
283 newTaxonNameForRegistration
= TaxonNameFactory
.NewNameInstance(RegistrationUIDefaults
.NOMENCLATURAL_CODE
, Rank
.SPECIES());
284 newTaxonNameForRegistration
.setNomenclaturalReference(getRepo().getReferenceService().find(workingset
.getCitationId()));
285 EntityChangeEvent nameSaveEvent
= getTaxonNameStore().saveBean(newTaxonNameForRegistration
);
286 newTaxonNameForRegistration
= getRepo().getNameService().find(nameSaveEvent
.getEntityId());
287 TaxonNamePopupEditor popup
= getNavigationManager().showInPopup(TaxonNamePopupEditor
.class);
288 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
,CRUD
.DELETE
));
289 popup
.withDeleteButton(true);
290 configureTaxonNameEditor(popup
);
291 popup
.loadInEditor(newTaxonNameForRegistration
.getId());
295 * TODO consider putting this into a Configurer Bean per UIScope.
296 * In the configurator bean this methods popup papamerter should be of the type
297 * AbstractPopupEditor
301 protected void configureTaxonNameEditor(TaxonNamePopupEditor popup
) {
302 popup
.enableMode(TaxonNamePopupEditorMode
.suppressReplacementAuthorshipData
);
303 popup
.enableMode(TaxonNamePopupEditorMode
.nomenclaturalReferenceSectionEditingOnly
);
307 * Creates a new <code>Registration</code> for a new name that has just been edited
308 * using the <code>TaxonNamePopupEditor</code>. The new name was previously created
309 * in this presenter as <code>newTaxonNameForRegistration</code> (see {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)})
310 * and is either filled with data (<code>Reason.SAVE</code>) or it is still empty
311 * (<code>Reason.CANCEL</code>).
315 * @throws RegistrationValidationException
318 public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
319 if(event
.getPopup() instanceof TaxonNamePopupEditor
){
320 TransactionStatus txStatus
= getRepo().startTransaction();
321 if(event
.getReason().equals(Reason
.SAVE
)){
322 if(newTaxonNameForRegistration
!= null){
323 int taxonNameId
= newTaxonNameForRegistration
.getId();
324 getRepo().getSession().refresh(newTaxonNameForRegistration
);
325 Registration reg
= createNewRegistrationForName(taxonNameId
);
326 // reload workingset into current session
327 loadWorkingSet(workingset
.getCitationId());
331 } else if(event
.getReason().equals(Reason
.CANCEL
)){
332 if(newTaxonNameForRegistration
!= null){
334 getTaxonNameStore().deleteBean(newTaxonNameForRegistration
);
337 getRepo().commitTransaction(txStatus
);
338 newTaxonNameForRegistration
= null;
344 * Creates a new Registration for an exiting (previously published name).
347 * @throws RegistrationValidationException
349 @EventListener(condition
= "#event.action == T(eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkingsetAction.Action).start")
350 public void onRegistrationWorkflowEventActionStart(RegistrationWorkingsetAction event
) throws RegistrationValidationException
{
352 getView().getAddExistingNameCombobox().commit();
353 TaxonName typifiedName
= getView().getAddExistingNameCombobox().getValue();
354 if(typifiedName
!= null){
355 Registration newRegistrationWithExistingName
= createNewRegistrationForName(null);
356 Reference citation
= getRepo().getReferenceService().find(workingset
.getCitationId());
357 newRegistrationDTOWithExistingName
= new RegistrationDTO(newRegistrationWithExistingName
, typifiedName
, citation
);
358 workingset
.add(newRegistrationDTOWithExistingName
);
359 // tell the view to update the workingset
360 getView().setWorkingset(workingset
);
361 getView().getAddExistingNameRegistrationButton().setEnabled(false);
362 getView().getAddExistingNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
364 logger
.error("Seletced name is NULL");
369 @EventListener(condition
= "#event.type == T(eu.etaxonomy.vaadin.event.EditorActionType).EDIT")
370 public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event
) {
372 if(!checkFromOwnView(event
)){
376 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
377 SpecimenTypeDesignationWorkingsetPopupEditor popup
= getNavigationManager().showInPopup(SpecimenTypeDesignationWorkingsetPopupEditor
.class);
378 popup
.withDeleteButton(true);
379 popup
.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event
.getRegistrationId(), event
.getEntityId()));
380 if(event
.getSourceComponent() != null){
381 popup
.setReadOnly(event
.getSourceComponent().isReadOnly());
384 // TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET
385 // FIXME implement NameTypeDesignationWorkingsetPopupEditor
389 @EventListener(condition
= "#event.type == T(eu.etaxonomy.vaadin.event.EditorActionType).ADD && #event.sourceComponent == null")
390 public void onAddNewTypeDesignationWorkingset(TypeDesignationWorkingsetEditorAction event
) {
392 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
393 SpecimenTypeDesignationWorkingsetPopupEditor popup
= getNavigationManager().showInPopup(SpecimenTypeDesignationWorkingsetPopupEditor
.class);
394 TypeDesignationWorkingsetEditorIdSet identifierSet
;
395 Integer typifiedNameId
;
396 if(newRegistrationDTOWithExistingName
!= null){
397 typifiedNameId
= newRegistrationDTOWithExistingName
.getTypifiedNameRef().getId();
399 RegistrationDTO registrationDTO
= workingset
.getRegistrationDTO(event
.getRegistrationId()).get();
400 EntityReference typifiedNameRef
= registrationDTO
.getTypifiedNameRef();
401 if(typifiedNameRef
!= null){
402 // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
403 typifiedNameId
= typifiedNameRef
.getId();
405 // case of registrations with a name in the nomenclatural act.
406 typifiedNameId
= registrationDTO
.getNameRef().getId();
409 identifierSet
= new TypeDesignationWorkingsetEditorIdSet(
410 event
.getRegistrationId(),
411 getView().getCitationID(),
414 popup
.grantToCurrentUser(EnumSet
.of(CRUD
.UPDATE
, CRUD
.DELETE
));
415 popup
.loadInEditor(identifierSet
);
416 popup
.withDeleteButton(true);
418 // TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET
419 // FIXME implement NameTypeDesignationWorkingsetPopupEditor
424 * Performs final actions after a TypeDesignationEditor which has been
425 * opened to add a TypeDesignation to a Registration object which was
426 * created for an previously published name. Prior adding a typedesignation,
427 * the according Registration object is dangling, that has no association to
428 * any entity denoting an nomenclatural act which has a reference to a
429 * publication. This means that the registration object is not in the
434 * @throws RegistrationValidationException
437 public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
438 if(event
.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor
){
439 if(event
.getReason().equals(Reason
.SAVE
)){
441 } else if(event
.getReason().equals(Reason
.CANCEL
)){
443 if(newRegistrationDTOWithExistingName
!= null){
444 getRegistrationStore().deleteBean(newRegistrationDTOWithExistingName
.registration());
447 // set newRegistrationDTOWithExistingName NULL in any case
448 newRegistrationDTOWithExistingName
= null;
453 @EventListener(classes
=ShowDetailsEvent
.class, condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet)")
454 public void onShowRegistrationWorkingSetMessages(ShowDetailsEvent
<?
,?
> event
) { // WARNING don't use more specific generic type arguments
455 List
<String
> messages
= new ArrayList
<>();
456 for(RegistrationDTO dto
: workingset
.getRegistrationDTOs()){
457 dto
.getMessages().forEach(m
-> messages
.add(dto
.getSummary() + ": " + m
));
459 if(event
.getProperty().equals("messages")){
460 getView().openDetailsPopup("Messages", messages
);
464 @EventListener(classes
=ShowDetailsEvent
.class, condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.view.registration.RegistrationDTO)")
465 public void onShowRegistrationMessages(ShowDetailsEvent
<?
,?
> event
) { // WARNING don't use more specific generic type arguments
466 RegistrationDTO regDto
= workingSetService
.loadDtoById((Integer
)event
.getIdentifier());
467 if(event
.getProperty().equals("messages")){
468 if(getView() != null){
469 getView().openDetailsPopup("Messages", regDto
.getMessages());
475 public void onEntityChangeEvent(EntityChangeEvent event
){
476 if(workingset
== null){
479 if(Reference
.class.isAssignableFrom(event
.getEntityType())){
480 if(workingset
.getCitationId().equals(event
.getEntityId())){
484 if(Registration
.class.isAssignableFrom(event
.getEntityType())){
485 if(workingset
.getRegistrations().stream().anyMatch(reg
-> reg
.getId() == event
.getEntityId())){
489 if(TaxonName
.class.isAssignableFrom(event
.getEntityType())){
490 if(workingset
.getRegistrationDTOs().stream().anyMatch(reg
->
491 reg
.getTypifiedNameRef() != null
492 && reg
.getTypifiedNameRef().getId() == event
.getEntityId())){
496 if(TypeDesignationBase
.class.isAssignableFrom(event
.getEntityType())){
497 if(workingset
.getRegistrationDTOs().stream().anyMatch(
498 reg
-> reg
.getTypeDesignations().stream().anyMatch(
499 td
-> td
.getId() == event
.getEntityId()