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
;
19 import com
.vaadin
.spring
.annotation
.SpringComponent
;
20 import com
.vaadin
.spring
.annotation
.ViewScope
;
21 import com
.vaadin
.ui
.Label
;
22 import com
.vaadin
.ui
.UI
;
23 import com
.vaadin
.ui
.VerticalLayout
;
24 import com
.vaadin
.ui
.Window
;
26 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
27 import eu
.etaxonomy
.cdm
.api
.service
.IRegistrationService
;
28 import eu
.etaxonomy
.cdm
.model
.common
.User
;
29 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
30 import eu
.etaxonomy
.cdm
.model
.name
.Registration
;
31 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
32 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameFactory
;
33 import eu
.etaxonomy
.cdm
.model
.name
.TypeDesignationBase
;
34 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
35 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CRUD
;
36 import eu
.etaxonomy
.cdm
.service
.CdmFilterablePagingProvider
;
37 import eu
.etaxonomy
.cdm
.service
.CdmStore
;
38 import eu
.etaxonomy
.cdm
.service
.IRegistrationWorkingSetService
;
39 import eu
.etaxonomy
.cdm
.vaadin
.event
.EntityChangeEvent
;
40 import eu
.etaxonomy
.cdm
.vaadin
.event
.ReferenceEditorAction
;
41 import eu
.etaxonomy
.cdm
.vaadin
.event
.RegistrationEditorAction
;
42 import eu
.etaxonomy
.cdm
.vaadin
.event
.ShowDetailsEvent
;
43 import eu
.etaxonomy
.cdm
.vaadin
.event
.TaxonNameEditorAction
;
44 import eu
.etaxonomy
.cdm
.vaadin
.event
.TypeDesignationWorkingsetEditorAction
;
45 import eu
.etaxonomy
.cdm
.vaadin
.event
.registration
.RegistrationWorkflowEvent
;
46 import eu
.etaxonomy
.cdm
.vaadin
.model
.EntityReference
;
47 import eu
.etaxonomy
.cdm
.vaadin
.model
.registration
.RegistrationWorkingSet
;
48 import eu
.etaxonomy
.cdm
.vaadin
.security
.UserHelper
;
49 import eu
.etaxonomy
.cdm
.vaadin
.util
.CdmTitleCacheCaptionGenerator
;
50 import eu
.etaxonomy
.cdm
.vaadin
.util
.converter
.TypeDesignationSetManager
.TypeDesignationWorkingSetType
;
51 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.SpecimenTypeDesignationWorkingsetPopupEditor
;
52 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TaxonNamePopupEditor
;
53 import eu
.etaxonomy
.cdm
.vaadin
.view
.name
.TypeDesignationWorkingsetEditorIdSet
;
54 import eu
.etaxonomy
.cdm
.vaadin
.view
.reference
.ReferencePopupEditor
;
55 import eu
.etaxonomy
.vaadin
.mvp
.AbstractPresenter
;
56 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
;
57 import eu
.etaxonomy
.vaadin
.ui
.view
.DoneWithPopupEvent
.Reason
;
60 * @author a.kohlbecker
66 public class RegistrationWorkingsetPresenter
extends AbstractPresenter
<RegistrationWorkingsetView
> {
68 private static final long serialVersionUID
= 1L;
71 private IRegistrationWorkingSetService workingSetService
;
74 * @return the workingSetService
76 public IRegistrationWorkingSetService
getWorkingSetService() {
77 ensureBoundConversation();
78 return workingSetService
;
81 private RegistrationWorkingSet workingset
;
83 private TaxonName newTaxonNameForRegistration
= null;
85 private RegistrationDTO newRegistrationDTOWithExistingName
;
91 public RegistrationWorkingsetPresenter() {
96 * Always create a new Store
100 protected CdmStore
<Registration
, IRegistrationService
> getRegistrationStore(){
101 return new CdmStore
<Registration
, IRegistrationService
>(getRepo(), getRepo().getRegistrationService());
105 * Always create a new Store
109 protected CdmStore
<TaxonName
, INameService
> getTaxonNameStore(){
110 return new CdmStore
<TaxonName
, INameService
>(getRepo(), getRepo().getNameService());
118 protected Registration
createNewRegistrationForName(Integer taxonNameId
) {
119 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120 // move into RegistrationWorkflowStateMachine
121 long identifier
= System
.currentTimeMillis();
122 Registration reg
= Registration
.NewInstance(
123 "http://phycobank.org/" + identifier
,
125 taxonNameId
!= null ?
getRepo().getNameService().find(taxonNameId
) : null,
127 Authentication authentication
= currentSecurityContext().getAuthentication();
128 reg
.setSubmitter((User
)authentication
.getPrincipal());
129 EntityChangeEvent event
= getRegistrationStore().saveBean(reg
);
130 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131 return getRepo().getRegistrationService().find(event
.getEntityId());
138 protected void refreshView() {
139 getConversationHolder().getSession().clear();
140 presentWorkingSet(workingset
.getCitationId());
148 public void handleViewEntered() {
150 super.handleViewEntered();
152 presentWorkingSet(getView().getCitationID());
154 CdmFilterablePagingProvider
<TaxonName
> pagingProvider
= new CdmFilterablePagingProvider
<TaxonName
>(
155 getRepo().getNameService(), this);
156 CdmTitleCacheCaptionGenerator
<TaxonName
> titleCacheGenrator
= new CdmTitleCacheCaptionGenerator
<TaxonName
>();
157 getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenrator
);
158 getView().getAddExistingNameCombobox().loadFrom(pagingProvider
, pagingProvider
, pagingProvider
.getPageSize());
162 * Loads the WorkingSet from the data base and passes it to the view.
164 * @param registrationID
166 private void presentWorkingSet(Integer referenceID
) {
168 workingset
= getWorkingSetService().loadWorkingSetByReferenceID(referenceID
);
169 } catch (RegistrationValidationException error
) {
171 Window errorDialog
= new Window("Validation Error");
172 errorDialog
.setModal(true);
173 VerticalLayout subContent
= new VerticalLayout();
174 subContent
.setMargin(true);
175 errorDialog
.setContent(subContent
);
176 subContent
.addComponent(new Label(error
.getMessage()));
177 UI
.getCurrent().addWindow(errorDialog
);
179 if(workingset
== null || workingset
.getCitationId() == null){
180 Reference citation
= getRepo().getReferenceService().find(referenceID
);
181 workingset
= new RegistrationWorkingSet(citation
);
183 // getView().setHeaderText("Registrations for " + workingset.getCitation());
184 getView().setWorkingset(workingset
);
187 @EventListener(condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).ADD && #event.sourceComponent == null")
188 public void onReferenceEditorActionAdd(ReferenceEditorAction event
) {
189 ReferencePopupEditor popup
= getNavigationManager().showInPopup(ReferencePopupEditor
.class);
190 popup
.loadInEditor(null);
193 @EventListener(condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
194 public void onReferenceEditorActionEdit(ReferenceEditorAction event
) {
195 ReferencePopupEditor popup
= getNavigationManager().showInPopup(ReferencePopupEditor
.class);
196 popup
.withDeleteButton(true);
197 popup
.loadInEditor(event
.getEntityId());
200 @EventListener(condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
201 public void onRegistrationEditorAction(RegistrationEditorAction event
) {
202 RegistrationPopupEditor popup
= getNavigationManager().showInPopup(RegistrationPopupEditor
.class);
203 popup
.loadInEditor(event
.getEntityId());
206 @EventListener(condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
207 public void onTaxonNameEditorActionEdit(TaxonNameEditorAction event
) {
209 TaxonNamePopupEditor popup
= getNavigationManager().showInPopup(TaxonNamePopupEditor
.class);
210 popup
.withDeleteButton(true);
211 // disable NomReferenceCombobox:
212 // the in the registration application inReferences should only edited centrally
213 popup
.getNomReferenceCombobox().setEnabled(false);
214 popup
.loadInEditor(event
.getEntityId());
217 @EventListener(condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).ADD")
218 public void onTaxonNameEditorActionAdd(TaxonNameEditorAction event
) {
220 newTaxonNameForRegistration
= TaxonNameFactory
.NewBotanicalInstance(Rank
.SPECIES());
221 newTaxonNameForRegistration
.setNomenclaturalReference(getRepo().getReferenceService().find(workingset
.getCitationId()));
222 EntityChangeEvent nameSaveEvent
= getTaxonNameStore().saveBean(newTaxonNameForRegistration
);
223 UserHelper
.fromSession().createAuthorityForCurrentUser(TaxonName
.class, nameSaveEvent
.getEntityId(), EnumSet
.of(CRUD
.UPDATE
,CRUD
.DELETE
), null);
224 newTaxonNameForRegistration
= getRepo().getNameService().find(nameSaveEvent
.getEntityId());
225 TaxonNamePopupEditor popup
= getNavigationManager().showInPopup(TaxonNamePopupEditor
.class);
226 popup
.withDeleteButton(true);
227 popup
.loadInEditor(newTaxonNameForRegistration
.getId());
228 // disable NomReferenceCombobox:
229 // the in the registration application inReferences should only edited centrally
230 popup
.getNomReferenceCombobox().setEnabled(false);
234 * Creates a new <code>Registration</code> for a new name that has just been edited
235 * using the <code>TaxonNamePopupEditor</code>. The new name was previously created
236 * in this presenter as <code>newTaxonNameForRegistration</code> (see {@link #onTaxonNameEditorActionAdd(TaxonNameEditorAction)})
237 * and is either filled with data (<code>Reason.SAVE</code>) or it is still empty
238 * (<code>Reason.CANCEL</code>).
242 * @throws RegistrationValidationException
245 public void onDoneWithTaxonnameEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
246 if(event
.getPopup() instanceof TaxonNamePopupEditor
){
247 if(event
.getReason().equals(Reason
.SAVE
)){
248 if(newTaxonNameForRegistration
!= null){
249 int taxonNameId
= newTaxonNameForRegistration
.getId();
250 Registration reg
= createNewRegistrationForName(taxonNameId
);
254 } else if(event
.getReason().equals(Reason
.CANCEL
)){
256 getTaxonNameStore().deleteBean(newTaxonNameForRegistration
);
258 newTaxonNameForRegistration
= null;
264 * Creates a new Registration for an exiting (previously published name).
267 * @throws RegistrationValidationException
269 @EventListener(condition
= "#event.action == T(eu.etaxonomy.cdm.vaadin.event.registration.RegistrationWorkflowEvent.Action).start")
270 public void onRegistrationWorkflowEventActionStart(RegistrationWorkflowEvent event
) throws RegistrationValidationException
{
272 getView().getAddExistingNameCombobox().commit();
273 TaxonName typifiedName
= getView().getAddExistingNameCombobox().getValue();
274 if(typifiedName
!= null){
275 Registration newRegistrationWithExistingName
= createNewRegistrationForName(null);
276 Reference citation
= getRepo().getReferenceService().find(workingset
.getCitationId());
277 newRegistrationDTOWithExistingName
= new RegistrationDTO(newRegistrationWithExistingName
, typifiedName
, citation
);
278 workingset
.add(newRegistrationDTOWithExistingName
);
279 // tell the view to update the workingset
280 getView().setWorkingset(workingset
);
281 getView().getAddExistingNameRegistrationButton().setEnabled(false);
282 getView().getAddExistingNameRegistrationButton().setDescription("You first need to add a type designation to the previously created registration.");
284 logger
.error("Seletced name is NULL");
289 @EventListener(condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).EDIT && #event.sourceComponent == null")
290 public void onTypeDesignationsEditorActionEdit(TypeDesignationWorkingsetEditorAction event
) {
292 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
293 SpecimenTypeDesignationWorkingsetPopupEditor popup
= getNavigationManager().showInPopup(SpecimenTypeDesignationWorkingsetPopupEditor
.class);
294 popup
.loadInEditor(new TypeDesignationWorkingsetEditorIdSet(event
.getRegistrationId(), event
.getEntityId()));
296 // TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET
297 // FIXME implement NameTypeDesignationWorkingsetPopupEditor
301 @EventListener(condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.Action).ADD && #event.sourceComponent == null")
302 public void onAddNewTypeDesignationWorkingset(TypeDesignationWorkingsetEditorAction event
) {
304 if(event
.getWorkingSetType() == TypeDesignationWorkingSetType
.SPECIMEN_TYPE_DESIGNATION_WORKINGSET
){
305 SpecimenTypeDesignationWorkingsetPopupEditor popup
= getNavigationManager().showInPopup(SpecimenTypeDesignationWorkingsetPopupEditor
.class);
306 TypeDesignationWorkingsetEditorIdSet identifierSet
;
307 Integer typifiedNameId
;
308 if(newRegistrationDTOWithExistingName
!= null){
309 typifiedNameId
= newRegistrationDTOWithExistingName
.getTypifiedName().getId();
311 RegistrationDTO registrationDTO
= workingset
.getRegistrationDTO(event
.getRegistrationId()).get();
312 EntityReference typifiedNameRef
= registrationDTO
.getTypifiedName();
313 if(typifiedNameRef
!= null){
314 // case for registrations without name, in which case the typifiedName is only defined via the typedesignations
315 typifiedNameId
= typifiedNameRef
.getId();
317 // case of registrations with a name in the nomenclatural act.
318 typifiedNameId
= registrationDTO
.getName().getId();
321 identifierSet
= new TypeDesignationWorkingsetEditorIdSet(
322 event
.getRegistrationId(),
323 getView().getCitationID(),
326 popup
.loadInEditor(identifierSet
328 popup
.withDeleteButton(true);
330 // TypeDesignationWorkingSetType.NAME_TYPE_DESIGNATION_WORKINGSET
331 // FIXME implement NameTypeDesignationWorkingsetPopupEditor
336 * Performs final actions after a TypeDesignationEditor which has been
337 * opened to add a TypeDesignation to a Registration object which was
338 * created for an previously published name. Prior adding a typedesignation,
339 * the according Registration object is dangling, that has no association to
340 * any entity denoting an nomenclatural act which has a reference to a
341 * publication. This means that the registration object is not in the
346 * @throws RegistrationValidationException
349 public void onDoneWithTypeDesignationEditor(DoneWithPopupEvent event
) throws RegistrationValidationException
{
350 if(event
.getPopup() instanceof SpecimenTypeDesignationWorkingsetPopupEditor
){
351 if(event
.getReason().equals(Reason
.SAVE
)){
353 } else if(event
.getReason().equals(Reason
.CANCEL
)){
355 if(newRegistrationDTOWithExistingName
!= null){
356 getRegistrationStore().deleteBean(newRegistrationDTOWithExistingName
.registration());
359 // set newRegistrationDTOWithExistingName NULL in any case
360 newRegistrationDTOWithExistingName
= null;
365 @EventListener(classes
=ShowDetailsEvent
.class, condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.model.registration.RegistrationWorkingSet)")
366 public void onShowRegistrationWorkingSetMessages(ShowDetailsEvent
<?
,?
> event
) { // WARNING don't use more specific generic type arguments
367 List
<String
> messages
= new ArrayList
<>();
368 for(RegistrationDTO dto
: workingset
.getRegistrationDTOs()){
369 dto
.getMessages().forEach(m
-> messages
.add(dto
.getSummary() + ": " + m
));
371 if(event
.getProperty().equals("messages")){
372 getView().openDetailsPopup("Messages", messages
);
376 @EventListener(classes
=ShowDetailsEvent
.class, condition
= "#event.type == T(eu.etaxonomy.cdm.vaadin.view.registration.RegistrationDTO)")
377 public void onShowRegistrationMessages(ShowDetailsEvent
<?
,?
> event
) { // WARNING don't use more specific generic type arguments
378 RegistrationDTO regDto
= workingSetService
.loadDtoById((Integer
)event
.getIdentifier());
379 if(event
.getProperty().equals("messages")){
380 if(getView() != null){
381 getView().openDetailsPopup("Messages", regDto
.getMessages());
387 public void onEntityChangeEvent(EntityChangeEvent event
){
388 if(workingset
== null){
391 if(Reference
.class.isAssignableFrom(event
.getEntityType())){
392 if(workingset
.getCitationId().equals(event
.getEntityId())){
396 if(Registration
.class.isAssignableFrom(event
.getEntityType())){
397 if(workingset
.getRegistrations().stream().anyMatch(reg
-> reg
.getId() == event
.getEntityId())){
401 if(TaxonName
.class.isAssignableFrom(event
.getEntityType())){
402 if(workingset
.getRegistrationDTOs().stream().anyMatch(reg
->
403 reg
.getTypifiedName() != null
404 && reg
.getTypifiedName().getId() == event
.getEntityId())){
408 if(TypeDesignationBase
.class.isAssignableFrom(event
.getEntityType())){
409 if(workingset
.getRegistrationDTOs().stream().anyMatch(
410 reg
-> reg
.getTypeDesignations().stream().anyMatch(
411 td
-> td
.getId() == event
.getEntityId()