ref #7046 removing prepareAsFieldGroupDataSource() which was opening connectinos...
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / view / name / SpecimenTypeDesignationWorkingsetEditorPresenter.java
1 /**
2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.cdm.vaadin.view.name;
10
11 import java.util.EnumSet;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.Set;
15
16 import org.hibernate.Session;
17 import org.springframework.beans.factory.BeanFactory;
18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.vaadin.viritin.fields.AbstractElementCollection;
20
21 import eu.etaxonomy.cdm.api.service.IRegistrationService;
22 import eu.etaxonomy.cdm.model.common.VersionableEntity;
23 import eu.etaxonomy.cdm.model.location.Country;
24 import eu.etaxonomy.cdm.model.name.Registration;
25 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
26 import eu.etaxonomy.cdm.model.name.TaxonName;
27 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
28 import eu.etaxonomy.cdm.model.occurrence.Collection;
29 import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
30 import eu.etaxonomy.cdm.model.occurrence.DerivationEventType;
31 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
32 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
33 import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
34 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
35 import eu.etaxonomy.cdm.model.reference.Reference;
36 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
37 import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
38 import eu.etaxonomy.cdm.service.CdmStore;
39 import eu.etaxonomy.cdm.service.IRegistrationWorkingSetService;
40 import eu.etaxonomy.cdm.service.RegistrationWorkingSetService;
41 import eu.etaxonomy.cdm.vaadin.component.CdmBeanItemContainerFactory;
42 import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityButtonUpdater;
43 import eu.etaxonomy.cdm.vaadin.model.TypedEntityReference;
44 import eu.etaxonomy.cdm.vaadin.model.registration.DerivationEventTypes;
45 import eu.etaxonomy.cdm.vaadin.model.registration.RegistrationTermLists;
46 import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationDTO;
47 import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationWorkingSetDTO;
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.TypeDesignationWorkingSet;
51 import eu.etaxonomy.cdm.vaadin.view.registration.RegistrationDTO;
52 import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
53 import eu.etaxonomy.vaadin.ui.view.PopupEditorFactory;
54 /**
55 * SpecimenTypeDesignationWorkingsetPopupEditorView implementation must override the showInEditor() method,
56 * see {@link #prepareAsFieldGroupDataSource()} for details.
57 *
58 * @author a.kohlbecker
59 * @since Jun 13, 2017
60 *
61 */
62 public class SpecimenTypeDesignationWorkingsetEditorPresenter
63 extends AbstractEditorPresenter<SpecimenTypeDesignationWorkingSetDTO , SpecimenTypeDesignationWorkingsetPopupEditorView> {
64
65 private static final long serialVersionUID = 4255636253714476918L;
66
67 CdmStore<Registration, IRegistrationService> store;
68
69 private Reference citation;
70
71 private TaxonName typifiedName;
72
73 /**
74 * This object for this field will either be injected by the {@link PopupEditorFactory} or by a Spring
75 * {@link BeanFactory}
76 */
77 @Autowired
78 private IRegistrationWorkingSetService registrationWorkingSetService;
79
80 /**
81 * if not null, this CRUD set is to be used to create a CdmAuthoritiy for the base entitiy which will be
82 * granted to the current use as long this grant is not assigned yet.
83 */
84 private EnumSet<CRUD> crud = null;
85
86 protected CdmStore<Registration, IRegistrationService> getStore() {
87 if(store == null){
88 store = new CdmStore<>(getRepo(), getRepo().getRegistrationService());
89 }
90 return store;
91 }
92
93
94 /**
95 * Loads an existing working set from the database. This process actually involves
96 * loading the Registration specified by the <code>RegistrationAndWorkingsetId.registrationId</code> and in
97 * a second step to find the workingset by the <code>registrationAndWorkingsetId.workingsetId</code>.
98 * <p>
99 * The <code>identifier</code> must be of the type {@link TypeDesignationWorkingsetEditorIdSet} whereas the field <code>egistrationId</code>
100 * must be present, the field <code>workingsetId</code>, however can be null. I this case a new workingset with a new {@link FieldUnit} as
101 * base entity is being created.
102 *
103 * @param identifier a {@link TypeDesignationWorkingsetEditorIdSet}
104 */
105 @Override
106 protected SpecimenTypeDesignationWorkingSetDTO loadBeanById(Object identifier) {
107
108 SpecimenTypeDesignationWorkingSetDTO workingSetDto;
109 if(identifier != null){
110
111 TypeDesignationWorkingsetEditorIdSet idset = (TypeDesignationWorkingsetEditorIdSet)identifier;
112
113 if(idset.workingsetId != null){
114 RegistrationDTO regDTO = registrationWorkingSetService.loadDtoById(idset.registrationId);
115 // find the working set
116 TypeDesignationWorkingSet typeDesignationWorkingSet = regDTO.getTypeDesignationWorkingSet(idset.workingsetId);
117 workingSetDto = regDTO.getSpecimenTypeDesignationWorkingSetDTO(typeDesignationWorkingSet.getBaseEntityReference());
118 citation = (Reference) regDTO.getCitation();
119 workingSetDto = fixMissingFieldUnit(workingSetDto);
120 } else {
121 // create a new workingset, for a new fieldunit which is the base for the workingset
122 FieldUnit newfieldUnit = FieldUnit.NewInstance();
123 Registration reg = getRepo().getRegistrationService().load(idset.registrationId,
124 RegistrationWorkingSetService.REGISTRATION_INIT_STRATEGY);
125 //TODO checkif passing reg as owner parameter is needed at all
126 workingSetDto = new SpecimenTypeDesignationWorkingSetDTO(reg, newfieldUnit, null);
127 citation = getRepo().getReferenceService().find(idset.publicationId);
128 typifiedName = getRepo().getNameService().find(idset.typifiedNameId);
129 }
130
131 } else {
132 workingSetDto = null;
133 }
134 return workingSetDto;
135 }
136
137
138 /**
139 * {@inheritDoc}
140 */
141 @SuppressWarnings("serial")
142 @Override
143 public void handleViewEntered() {
144
145 CdmBeanItemContainerFactory selectFactory = new CdmBeanItemContainerFactory(getRepo());
146 getView().getCountrySelectField().setContainerDataSource(selectFactory.buildBeanItemContainer(Country.uuidCountryVocabulary));
147
148 getView().getTypeDesignationsCollectionField().setEditorInstantiator(new AbstractElementCollection.Instantiator<SpecimenTypeDesignationDTORow>() {
149
150 CdmFilterablePagingProvider<Collection> collectionPagingProvider = new CdmFilterablePagingProvider<Collection>(getRepo().getCollectionService());
151
152 CdmFilterablePagingProvider<Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference>(getRepo().getReferenceService());
153
154 @Override
155 public SpecimenTypeDesignationDTORow create() {
156
157 SpecimenTypeDesignationDTORow row = new SpecimenTypeDesignationDTORow();
158
159 row.derivationEventType.setContainerDataSource(selectFactory.buildTermItemContainer(
160 RegistrationTermLists.DERIVATION_EVENT_TYPE_UUIDS())
161 );
162 row.derivationEventType.setNullSelectionAllowed(false);
163
164 row.derivationEventType.addValueChangeListener(e -> {
165 SpecimenTypeDesignationDTORow currentRow = row;
166 updateRowItemEnablement(currentRow);
167 });
168
169 row.typeStatus.setContainerDataSource(selectFactory.buildTermItemContainer(
170 RegistrationTermLists.SPECIMEN_TYPE_DESIGNATION_STATUS_UUIDS())
171 );
172 row.typeStatus.setNullSelectionAllowed(false);
173
174
175 row.collection.loadFrom(
176 collectionPagingProvider,
177 collectionPagingProvider,
178 collectionPagingProvider.getPageSize()
179 );
180 row.collection.getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<Collection>());
181 row.collection.getSelect().addValueChangeListener(new ToOneRelatedEntityButtonUpdater<Collection>(row.collection));
182
183 row.mediaSpecimenReference.loadFrom(
184 referencePagingProvider,
185 referencePagingProvider,
186 collectionPagingProvider.getPageSize()
187 );
188 row.mediaSpecimenReference.getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<Reference>());
189 row.mediaSpecimenReference.getSelect().addValueChangeListener(new ToOneRelatedEntityButtonUpdater<Reference>(row.mediaSpecimenReference));
190
191 getView().applyDefaultComponentStyle(row.components());
192
193 updateRowItemEnablement(row);
194
195 return row;
196 }
197
198 private void updateRowItemEnablement(SpecimenTypeDesignationDTORow row) {
199
200 DerivationEventType derivationEventType = (DerivationEventType)row.derivationEventType.getValue();
201
202 boolean publishedImageType = derivationEventType != null && derivationEventType.equals(DerivationEventTypes.PUBLISHED_IMAGE());
203 boolean unPublishedImageType = derivationEventType != null && derivationEventType.equals(DerivationEventTypes.UNPUBLISHED_IMAGE());
204
205 row.mediaSpecimenReference.setEnabled(publishedImageType);
206 row.mediaSpecimenReferenceDetail.setEnabled(publishedImageType);
207 row.mediaUri.setEnabled(unPublishedImageType);
208
209 }
210 });
211 }
212
213
214 private SpecimenTypeDesignationWorkingSetDTO fixMissingFieldUnit(SpecimenTypeDesignationWorkingSetDTO bean) {
215
216 if(bean.getFieldUnit() == null){
217 // in case the base unit of the working set is not a FieldUnit all contained TypeDesignations must be modified
218 // so that they are based on an empty FieldUnit with an associated Gathering Event
219 if(Registration.class.isAssignableFrom(bean.getOwner().getClass())){
220 // FIXME open Dialog to warn user about adding an empty fieldUnit to the typeDesignations
221 logger.info("Basing all typeDesignations on a new fieldUnit");
222 Session session = getSession();
223 Registration reg = getRepo().getRegistrationService().find(bean.getOwner().getId());
224 RegistrationDTO regDTO = new RegistrationDTO(reg);
225
226 FieldUnit fieldUnit = FieldUnit.NewInstance();
227 GatheringEvent gatheringEvent = GatheringEvent.NewInstance();
228 fieldUnit.setGatheringEvent(gatheringEvent);
229 getRepo().getOccurrenceService().save(fieldUnit);
230
231 VersionableEntity baseEntity = bean.getBaseEntity();
232 Set<TypeDesignationBase> typeDesignations = regDTO.getTypeDesignationsInWorkingSet(
233 new TypedEntityReference(baseEntity.getClass(), baseEntity.getId(), baseEntity.toString())
234 );
235 for(TypeDesignationBase td : typeDesignations){
236 DerivationEvent de = DerivationEvent.NewInstance();//
237 de.addOriginal(fieldUnit);
238 de.addDerivative(((SpecimenTypeDesignation)td).getTypeSpecimen());
239 de.setType(DerivationEventType.GATHERING_IN_SITU());
240 }
241
242 getRepo().getRegistrationService().saveOrUpdate(reg);
243 session.flush();
244 session.close();
245 } else {
246 throw new RuntimeException("Usupported owner type " + bean.getOwner().getClass() + ", needs to be implemented.");
247 }
248 }
249 return bean;
250 }
251
252
253
254 /**
255 * {@inheritDoc}
256 */
257 @Override
258 protected void saveBean(SpecimenTypeDesignationWorkingSetDTO dto) {
259
260 Registration reg = (Registration) dto.getOwner();
261
262 // associate all type designations with the fieldUnit
263 // 1. new ones are not yet associated
264 // 2. ones which had incomplete data are also not connected
265 for(SpecimenTypeDesignationDTO stdDTO : dto.getSpecimenTypeDesignationDTOs()){
266 try {
267 SpecimenOrObservationBase<?> original = findEarliestOriginal(stdDTO.asSpecimenTypeDesignation().getTypeSpecimen());
268 if(original instanceof DerivedUnit){
269 DerivedUnit du = (DerivedUnit)original;
270 du.getDerivedFrom().addOriginal(dto.getFieldUnit());
271 }
272 } catch (Exception e) {
273 // TODO Auto-generated catch block
274 e.printStackTrace();
275 }
276 }
277
278 // add newly added typeDesignations
279 Set<SpecimenTypeDesignation> addCandidates = new HashSet<>();
280 for(SpecimenTypeDesignationDTO stdDTO : dto.getSpecimenTypeDesignationDTOs()){
281 SpecimenTypeDesignation std = stdDTO.asSpecimenTypeDesignation();
282 if(reg.getTypeDesignations().isEmpty() || !reg.getTypeDesignations().stream().filter(td -> td.equals(std)).findFirst().isPresent()){
283 std.setCitation(citation);
284 typifiedName.addTypeDesignation(std, false);
285 addCandidates.add(std);
286 }
287 }
288 addCandidates.forEach(std -> reg.addTypeDesignation(std));
289
290
291 if(crud != null){
292 UserHelper.fromSession().createAuthorityForCurrentUser(dto.getFieldUnit(), crud, null);
293 }
294
295 getStore().saveBean(reg);
296 }
297
298 /**
299 * {@inheritDoc}
300 */
301 @Override
302 protected void deleteBean(SpecimenTypeDesignationWorkingSetDTO bean) {
303 // TODO Auto-generated method stub
304
305 }
306
307
308 /**
309 * @param std
310 * @return
311 * @throws Exception
312 */
313 private SpecimenOrObservationBase<?> findEarliestOriginal(DerivedUnit du) throws Exception {
314
315 SpecimenOrObservationBase original = du;
316
317 while(du != null && du.getDerivedFrom() != null && !du.getDerivedFrom().getOriginals().isEmpty()) {
318 Iterator<SpecimenOrObservationBase> it = du.getDerivedFrom().getOriginals().iterator();
319 SpecimenOrObservationBase nextOriginal = it.next();
320 if(nextOriginal == null){
321 break;
322 }
323 original = nextOriginal;
324 if(original instanceof DerivedUnit){
325 du = (DerivedUnit)original;
326 } else {
327 // so this must be a FieldUnit,
328 break;
329 }
330 if(it.hasNext()){
331 throw new Exception(String.format("%s has more than one originals", du.toString()));
332 }
333 }
334 return original;
335 }
336
337
338 /**
339 * @param crud
340 */
341 public void setGrantsForCurrentUser(EnumSet<CRUD> crud) {
342 this.crud = crud;
343
344 }
345
346
347 }