ref #7899 starting 'Incorrect name' editor without mode VALIDATE_AGAINST_HIGHER_NAME_...
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / view / name / SpecimenTypeDesignationWorkingsetPopupEditor.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.Collection;
12 import java.util.EnumSet;
13
14 import org.springframework.context.annotation.Scope;
15 import org.springframework.security.core.GrantedAuthority;
16 import org.vaadin.viritin.fields.ElementCollectionField;
17
18 import com.vaadin.data.Validator.InvalidValueException;
19 import com.vaadin.data.validator.DoubleRangeValidator;
20 import com.vaadin.server.ErrorMessage;
21 import com.vaadin.spring.annotation.SpringComponent;
22 import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
23 import com.vaadin.ui.Component;
24 import com.vaadin.ui.GridLayout;
25 import com.vaadin.ui.ListSelect;
26 import com.vaadin.ui.Panel;
27 import com.vaadin.ui.TextArea;
28
29 import eu.etaxonomy.cdm.model.common.AnnotationType;
30 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
31 import eu.etaxonomy.cdm.vaadin.component.CollectionRowRepresentative;
32 import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
33 import eu.etaxonomy.cdm.vaadin.component.common.GeoLocationField;
34 import eu.etaxonomy.cdm.vaadin.component.common.MinMaxTextField;
35 import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
36 import eu.etaxonomy.cdm.vaadin.component.common.TimePeriodField;
37 import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationDTO;
38 import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationWorkingSetDTO;
39 import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
40 import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
41 import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
42 import eu.etaxonomy.cdm.vaadin.util.converter.DoubleConverter;
43 import eu.etaxonomy.cdm.vaadin.util.converter.IntegerConverter;
44 import eu.etaxonomy.cdm.vaadin.view.PerEntityAuthorityGrantingEditor;
45 import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
46
47 /**
48 * @author a.kohlbecker
49 * @since May 15, 2017
50 *
51 */
52 @SpringComponent
53 @Scope("prototype")
54 public class SpecimenTypeDesignationWorkingsetPopupEditor
55 extends AbstractPopupEditor<SpecimenTypeDesignationWorkingSetDTO, SpecimenTypeDesignationWorkingsetEditorPresenter>
56 implements SpecimenTypeDesignationWorkingsetPopupEditorView, AccessRestrictedView, PerEntityAuthorityGrantingEditor {
57 /**
58 *
59 */
60 private static final String CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING = "Can't save as long as type designations are missing.";
61
62 /**
63 * @param layout
64 * @param dtoType
65 */
66 public SpecimenTypeDesignationWorkingsetPopupEditor() {
67 super(new GridLayout(), SpecimenTypeDesignationWorkingSetDTO.class);
68 GridLayout grid = (GridLayout) getFieldLayout();
69 grid.setMargin(true);
70 grid.setSpacing(true);
71 }
72
73 private static final long serialVersionUID = 5418275817834009509L;
74
75 private ListSelect countrySelectField;
76
77 private ElementCollectionField<SpecimenTypeDesignationDTO> typeDesignationsCollectionField;
78
79 private EnumSet<CRUD> crud;
80
81 private TeamOrPersonField collectorField;
82
83 private FilterableAnnotationsField annotationsListField;
84
85 private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
86
87 private GeoLocationField exactLocationField;
88
89 private Panel typeDesignationsScrollPanel;
90
91 /**
92 * @return the countrySelectField
93 */
94 @Override
95 public ListSelect getCountrySelectField() {
96 return countrySelectField;
97 }
98
99 /**
100 * {@inheritDoc}
101 */
102 @Override
103 protected void initContent() {
104
105 GridLayout grid = (GridLayout)getFieldLayout();
106 grid.setSpacing(true);
107 grid.setMargin(true);
108 grid.setColumns(3);
109 grid.setRows(10);
110
111 //TODO typifyingAuthors
112
113 // FieldUnit + GatheringEvent
114
115 int row = 0;
116 countrySelectField = new ListSelect("Country");
117 addField(countrySelectField, "country", 1, row , 2, row);
118 countrySelectField.setWidth("100%");
119 countrySelectField.setItemCaptionMode(ItemCaptionMode.PROPERTY);
120 countrySelectField.setItemCaptionPropertyId("label");
121 countrySelectField.setRows(1);
122
123 row++;
124 TextArea localityField = new TextArea("Locality");
125 localityField.setNullRepresentation("");
126 addField(localityField, "locality", 0, row , 2, row);
127 localityField.setWidth("100%");
128 // NOTE: setRows and SetCold breaks he width setting,
129 // see https://github.com/vaadin/framework/issues/3617
130
131 row++;
132 exactLocationField = new GeoLocationField("Geo location");
133 addField(exactLocationField, "exactLocation", 0, row, 2, row);
134 exactLocationField.setWidth("100%");
135
136 row++;
137 MinMaxTextField absElevationMinMax = new MinMaxTextField("Altitude", "m");
138 absElevationMinMax.setWidth("100%");
139 absElevationMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
140 grid.addComponent(absElevationMinMax, 0, row, 2, row);
141
142 bindField(absElevationMinMax.getMinField(), "absoluteElevation");
143 bindField(absElevationMinMax.getMaxField(), "absoluteElevationMax");
144 bindField(absElevationMinMax.getTextField(), "absoluteElevationText");
145
146 absElevationMinMax.getMaxField().setConverter(new IntegerConverter());
147 absElevationMinMax.getMinField().setConverter(new IntegerConverter());
148
149 row++;
150 MinMaxTextField distanceToWaterSurfaceMinMax = new MinMaxTextField("Distance to water surface", "m");
151 distanceToWaterSurfaceMinMax.setWidth("100%");
152 distanceToWaterSurfaceMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
153 grid.addComponent(distanceToWaterSurfaceMinMax, 0, row, 2, row);
154
155 bindField(distanceToWaterSurfaceMinMax.getMinField(), "distanceToWaterSurface");
156 bindField(distanceToWaterSurfaceMinMax.getMaxField(), "distanceToWaterSurfaceMax");
157 bindField(distanceToWaterSurfaceMinMax.getTextField(), "distanceToWaterSurfaceText");
158 distanceToWaterSurfaceMinMax.getMaxField().setConverter(new DoubleConverter());
159 distanceToWaterSurfaceMinMax.getMinField().setConverter(new DoubleConverter());
160 distanceToWaterSurfaceMinMax.getMaxField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double.MAX_VALUE));
161 distanceToWaterSurfaceMinMax.getMinField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double.MAX_VALUE));
162
163 row++;
164 MinMaxTextField distanceToGroundMinMax = new MinMaxTextField("Distance to substrate", "m");
165 distanceToGroundMinMax.setWidth("100%");
166 distanceToGroundMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
167 grid.addComponent(distanceToGroundMinMax, 0, row, 2, row);
168
169 bindField(distanceToGroundMinMax.getMinField(), "distanceToGround");
170 bindField(distanceToGroundMinMax.getMaxField(), "distanceToGroundMax");
171 bindField(distanceToGroundMinMax.getTextField(), "distanceToGroundText");
172 distanceToGroundMinMax.getMaxField().setConverter(new DoubleConverter());
173 distanceToGroundMinMax.getMinField().setConverter(new DoubleConverter());
174
175 row++;
176 collectorField = new TeamOrPersonField("Collector", TeamOrPersonBaseCaptionGenerator.CacheType.COLLECTOR_TITLE);
177 addField(collectorField, "collector", 0, row, 2, row);
178
179 row++;
180
181 TimePeriodField collectionDateField = new TimePeriodField("Collection date");
182 // collectionDateField.setInputPrompt("dd.mm.yyyy");
183 addField(collectionDateField, "gatheringDate", 0, row, 1, row);
184 addTextField("Field number", "fieldNumber", 2, row);
185
186
187 row++;
188
189 // FIXME: can we use the Grid instead?
190 typeDesignationsCollectionField = new ElementCollectionField<SpecimenTypeDesignationDTO>(
191 SpecimenTypeDesignationDTO.class,
192 SpecimenTypeDesignationDTORow.class
193 ){
194
195 @Override
196 public void commit() throws SourceException, InvalidValueException {
197 validate(); // validate always so that empty rows are recognized
198 super.commit();
199 }
200
201 @Override
202 public boolean isEmpty() {
203 Collection value = getValue();
204 return value == null || value.isEmpty() ;
205 }
206
207 @Override
208 public void setComponentError(ErrorMessage componentError) {
209 typeDesignationsScrollPanel.setComponentError(componentError);
210 }
211
212 };
213 typeDesignationsCollectionField.withCaption("Types");
214 typeDesignationsCollectionField.getLayout().setSpacing(false);
215 typeDesignationsCollectionField.getLayout().setColumns(3);
216 typeDesignationsCollectionField.setRequired(true); // only works with the above overwritten commit()
217 typeDesignationsCollectionField.setRequiredError(CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING);
218 typeDesignationsCollectionField.setVisibleProperties(SpecimenTypeDesignationDTORow.visibleFields());
219
220 typeDesignationsCollectionField.setPropertyHeader("accessionNumber", "Access. num.");
221 typeDesignationsCollectionField.setPropertyHeader("preferredStableUri", "Stable URI");
222 typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReference", "Image reference");
223 typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReferenceDetail", "Reference detail");
224 typeDesignationsCollectionField.addElementAddedListener( e -> typeDesignationsCollectionField.setComponentError(null));
225
226 // typeDesignationsCollectionField.getLayout().setMargin(false);
227 // typeDesignationsCollectionField.addStyleName("composite-field-wrapper");
228 // addField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs", 0, row, 2, row);
229
230 typeDesignationsScrollPanel = new Panel(typeDesignationsCollectionField.getLayout());
231 typeDesignationsScrollPanel.setCaption("Types");
232 typeDesignationsScrollPanel.setWidth(800, Unit.PIXELS);
233
234 bindField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs");
235 addComponent(typeDesignationsScrollPanel, 0, row, 2, row);
236
237 row++;
238 annotationsListField = new FilterableAnnotationsField("Editorial notes");
239 annotationsListField.setWidth(100, Unit.PERCENTAGE);
240 annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
241 addField(annotationsListField, "annotations", 0, row, 2, row);
242
243 }
244
245
246 /**
247 * {@inheritDoc}
248 */
249 @Override
250 public String getWindowCaption() {
251 return "Specimen typedesignations editor";
252 }
253
254 /**
255 * {@inheritDoc}
256 */
257 @Override
258 public void focusFirst() {
259 // none
260 }
261
262 /**
263 * {@inheritDoc}
264 */
265 @Override
266 protected String getDefaultComponentStyles() {
267 return "tiny";
268 }
269
270 /**
271 * {@inheritDoc}
272 */
273 @Override
274 public boolean allowAnonymousAccess() {
275 return false;
276 }
277
278 /**
279 * {@inheritDoc}
280 */
281 @Override
282 public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
283 return null;
284 }
285
286 /**
287 * {@inheritDoc}
288 */
289 @Override
290 public boolean isResizable() {
291 return true;
292 }
293
294
295 // ------- SpecimenTypeDesignationWorkingsetPopupEditorView methods ---- //
296 @Override
297 public ElementCollectionField<SpecimenTypeDesignationDTO> getTypeDesignationsCollectionField() {
298 return typeDesignationsCollectionField;
299 }
300
301 @Override
302 public void applyDefaultComponentStyle(Component ... components){
303 for(int i = 0; i <components.length; i++){
304 components[i].setStyleName(getDefaultComponentStyles());
305 }
306 }
307
308 /**
309 * {@inheritDoc}
310 */
311 @Override
312 public void grantToCurrentUser(EnumSet<CRUD> crud) {
313 getPresenter().setGrantsForCurrentUser(crud);
314
315 }
316
317 /**
318 * {@inheritDoc}
319 */
320 @Override
321 protected void afterItemDataSourceSet() {
322 super.afterItemDataSourceSet();
323 GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
324 for(int rowIndex = 1; rowIndex < gridLayout.getRows(); rowIndex++){ // first row is header
325 Component item = gridLayout.getComponent(SpecimenTypeDesignationDTORow.rowListSelectColumn(), rowIndex);
326 ((CollectionRowRepresentative)item).updateRowItemsEnabledStates();
327 }
328 updateAllowDelete();
329 }
330
331 /**
332 * {@inheritDoc}
333 */
334 @Override
335 public void updateAllowDelete(){
336 // disable the delete button if there is only one typeDesignation
337 // if this typeDesignation is deleted the fieldUnit would become orphan in the
338 // TypeDesignationWorkingSet
339 GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
340 if(gridLayout.getRows() == 3){ // first row is header, last row is next new item
341 gridLayout.getComponent(gridLayout.getColumns() - 1, 1).setEnabled(false);
342 }
343 }
344
345
346 /**
347 * {@inheritDoc}
348 */
349 @Override
350 public void setReadOnly(boolean readOnly) {
351 super.setReadOnly(readOnly);
352 getFieldLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
353 collectorField.setEditorReadOnly(readOnly);
354 typeDesignationsCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
355
356 }
357
358 /**
359 * @return the collectorField
360 */
361 @Override
362 public TeamOrPersonField getCollectorField() {
363 return collectorField;
364 }
365
366 /**
367 * By default AnnotationType.EDITORIAL() is enabled.
368 *
369 * @return the editableAnotationTypes
370 */
371 @Override
372 public AnnotationType[] getEditableAnotationTypes() {
373 return editableAnotationTypes;
374 }
375
376 /**
377 * By default AnnotationType.EDITORIAL() is enabled.
378 *
379 *
380 * @param editableAnotationTypes the editableAnotationTypes to set
381 */
382 @Override
383 public void setEditableAnotationTypes(AnnotationType ... editableAnotationTypes) {
384 this.editableAnotationTypes = editableAnotationTypes;
385 }
386
387 /**
388 * {@inheritDoc}
389 */
390 @Override
391 public FilterableAnnotationsField getAnnotationsField() {
392 return annotationsListField;
393 }
394
395 @Override
396 public GeoLocationField getExactLocationField() {
397 return exactLocationField;
398 }
399
400
401
402 }