Project

General

Profile

Download (15.4 KB) Statistics
| Branch: | Tag: | Revision:
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.shared.ui.MarginInfo;
22
import com.vaadin.spring.annotation.SpringComponent;
23
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
24
import com.vaadin.ui.Component;
25
import com.vaadin.ui.GridLayout;
26
import com.vaadin.ui.NativeSelect;
27
import com.vaadin.ui.Panel;
28
import com.vaadin.ui.TextArea;
29

    
30
import eu.etaxonomy.cdm.api.utility.RoleProber;
31
import eu.etaxonomy.cdm.model.common.AnnotationType;
32
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
33
import eu.etaxonomy.cdm.service.UserHelperAccess;
34
import eu.etaxonomy.cdm.vaadin.component.CollectionRowRepresentative;
35
import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
36
import eu.etaxonomy.cdm.vaadin.component.common.GeoLocationField;
37
import eu.etaxonomy.cdm.vaadin.component.common.MinMaxTextField;
38
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
39
import eu.etaxonomy.cdm.vaadin.component.common.TimePeriodField;
40
import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationDTO;
41
import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationWorkingSetDTO;
42
import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
43
import eu.etaxonomy.cdm.vaadin.permission.RolesAndPermissions;
44
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
45
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
46
import eu.etaxonomy.cdm.vaadin.util.converter.DoubleConverter;
47
import eu.etaxonomy.cdm.vaadin.util.converter.IntegerConverter;
48
import eu.etaxonomy.cdm.vaadin.view.PerEntityAuthorityGrantingEditor;
49
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
50

    
51
/**
52
 * @author a.kohlbecker
53
 * @since May 15, 2017
54
 *
55
 * TODO as subclass of AbstractCdmPopupEditor?
56
 *
57
 */
58
@SpringComponent
59
@Scope("prototype")
60
public class SpecimenTypeDesignationWorkingsetPopupEditor
61
    extends AbstractPopupEditor<SpecimenTypeDesignationWorkingSetDTO, SpecimenTypeDesignationWorkingsetEditorPresenter>
62
    implements SpecimenTypeDesignationWorkingsetPopupEditorView, AccessRestrictedView, PerEntityAuthorityGrantingEditor {
63
    /**
64
     *
65
     */
66
    private static final String CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING = "Can't save as long as type designations are missing.";
67

    
68
    /**
69
     * @param layout
70
     * @param dtoType
71
     */
72
    public SpecimenTypeDesignationWorkingsetPopupEditor() {
73
        super(new GridLayout(), SpecimenTypeDesignationWorkingSetDTO.class);
74
        GridLayout grid = (GridLayout) getFieldLayout();
75
        grid.setMargin(true);
76
        grid.setSpacing(true);
77
    }
78

    
79
    private static final long serialVersionUID = 5418275817834009509L;
80

    
81
    private NativeSelect countrySelectField;
82

    
83
    private ElementCollectionField<SpecimenTypeDesignationDTO> typeDesignationsCollectionField;
84

    
85
    private EnumSet<CRUD> crud;
86

    
87
    private TeamOrPersonField collectorField;
88

    
89
    private FilterableAnnotationsField annotationsListField;
90

    
91
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
92

    
93
    private GeoLocationField exactLocationField;
94

    
95
    private Panel typeDesignationsScrollPanel;
96

    
97
    private String accessDeniedMessage;
98

    
99
    /**
100
     * @return the countrySelectField
101
     */
102
    @Override
103
    public NativeSelect getCountrySelectField() {
104
        return countrySelectField;
105
    }
106

    
107
    /**
108
     * {@inheritDoc}
109
     */
110
    @Override
111
    protected void initContent() {
112

    
113
        GridLayout grid = (GridLayout)getFieldLayout();
114
        grid.setSpacing(true);
115
        grid.setMargin(true);
116
        grid.setColumns(3);
117
        grid.setRows(10);
118

    
119
        //TODO typifyingAuthors
120

    
121
        // FieldUnit + GatheringEvent
122

    
123
        int row = 0;
124
        countrySelectField = new NativeSelect("Country");
125
        addField(countrySelectField, "country", 1, row , 2, row);
126
        countrySelectField.setWidth("100%");
127
        countrySelectField.setItemCaptionMode(ItemCaptionMode.PROPERTY);
128
        countrySelectField.setItemCaptionPropertyId("label");
129

    
130
        row++;
131
        TextArea localityField = new TextArea("Locality");
132
        localityField.setNullRepresentation("");
133
        addField(localityField, "locality", 0, row , 2, row);
134
        localityField.setWidth("100%");
135
        // NOTE: setRows and SetCold breaks he width setting,
136
        //        see https://github.com/vaadin/framework/issues/3617
137

    
138
        row++;
139
        exactLocationField = new GeoLocationField("Geo location");
140
        addField(exactLocationField, "exactLocation", 0, row, 2, row);
141
        exactLocationField.setWidth("100%");
142

    
143
        row++;
144
        MinMaxTextField absElevationMinMax = new MinMaxTextField("Altitude", "m");
145
        absElevationMinMax.setWidth("100%");
146
        absElevationMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
147
        grid.addComponent(absElevationMinMax, 0, row, 2, row);
148

    
149
        bindField(absElevationMinMax.getMinField(), "absoluteElevation");
150
        bindField(absElevationMinMax.getMaxField(), "absoluteElevationMax");
151
        bindField(absElevationMinMax.getTextField(), "absoluteElevationText");
152

    
153
        absElevationMinMax.getMaxField().setConverter(new IntegerConverter());
154
        absElevationMinMax.getMinField().setConverter(new IntegerConverter());
155

    
156
        row++;
157
        MinMaxTextField distanceToWaterSurfaceMinMax = new MinMaxTextField("Distance to water surface", "m");
158
        distanceToWaterSurfaceMinMax.setWidth("100%");
159
        distanceToWaterSurfaceMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
160
        grid.addComponent(distanceToWaterSurfaceMinMax, 0, row, 2, row);
161

    
162
        bindField(distanceToWaterSurfaceMinMax.getMinField(), "distanceToWaterSurface");
163
        bindField(distanceToWaterSurfaceMinMax.getMaxField(), "distanceToWaterSurfaceMax");
164
        bindField(distanceToWaterSurfaceMinMax.getTextField(), "distanceToWaterSurfaceText");
165
        distanceToWaterSurfaceMinMax.getMaxField().setConverter(new DoubleConverter());
166
        distanceToWaterSurfaceMinMax.getMinField().setConverter(new DoubleConverter());
167
        distanceToWaterSurfaceMinMax.getMaxField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double.MAX_VALUE));
168
        distanceToWaterSurfaceMinMax.getMinField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double.MAX_VALUE));
169

    
170
        row++;
171
        MinMaxTextField distanceToGroundMinMax = new MinMaxTextField("Distance to substrate", "m");
172
        distanceToGroundMinMax.setWidth("100%");
173
        distanceToGroundMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
174
        grid.addComponent(distanceToGroundMinMax, 0, row, 2, row);
175

    
176
        bindField(distanceToGroundMinMax.getMinField(), "distanceToGround");
177
        bindField(distanceToGroundMinMax.getMaxField(), "distanceToGroundMax");
178
        bindField(distanceToGroundMinMax.getTextField(), "distanceToGroundText");
179
        distanceToGroundMinMax.getMaxField().setConverter(new DoubleConverter());
180
        distanceToGroundMinMax.getMinField().setConverter(new DoubleConverter());
181

    
182
        row++;
183
        collectorField = new TeamOrPersonField("Collector", TeamOrPersonBaseCaptionGenerator.CacheType.COLLECTOR_TITLE);
184
        addField(collectorField, "collector", 0, row, 2, row);
185

    
186
        row++;
187

    
188
        TimePeriodField collectionDateField = new TimePeriodField("Collection date");
189
        // collectionDateField.setInputPrompt("dd.mm.yyyy");
190
        addField(collectionDateField, "gatheringDate", 0, row, 1, row);
191
        addTextField("Field number", "fieldNumber", 2, row);
192

    
193

    
194
        row++;
195

    
196
        // FIXME: can we use the Grid instead?
197
        typeDesignationsCollectionField = new ElementCollectionField<SpecimenTypeDesignationDTO>(
198
                SpecimenTypeDesignationDTO.class,
199
                SpecimenTypeDesignationDTORow.class
200
                ){
201

    
202
                    @Override
203
                    public void commit() throws SourceException, InvalidValueException {
204
                        validate(); // validate always so that empty rows are recognized
205
                        super.commit();
206
                    }
207

    
208
                    @Override
209
                    public boolean isEmpty() {
210
                        Collection value = getValue();
211
                        return value == null || value.isEmpty() ;
212
                    }
213

    
214
                    @Override
215
                    public void setComponentError(ErrorMessage componentError) {
216
                        typeDesignationsScrollPanel.setComponentError(componentError);
217
                    }
218

    
219
        };
220
        typeDesignationsCollectionField.withCaption("Types");
221
        typeDesignationsCollectionField.getLayout().setSpacing(false);
222
        typeDesignationsCollectionField.getLayout().setColumns(3);
223
        typeDesignationsCollectionField.setRequired(true); // only works with the above overwritten commit()
224
        typeDesignationsCollectionField.setRequiredError(CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING);
225
        typeDesignationsCollectionField.setVisibleProperties(SpecimenTypeDesignationDTORow.visibleFields());
226

    
227
        typeDesignationsCollectionField.setPropertyHeader("accessionNumber", "Access. num.");
228
        typeDesignationsCollectionField.setPropertyHeader("preferredStableUri", "Stable URI");
229
        typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReference", "Image reference");
230
        typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReferenceDetail", "Reference detail");
231
        typeDesignationsCollectionField.addElementAddedListener( e -> typeDesignationsCollectionField.setComponentError(null));
232
        typeDesignationsCollectionField.getLayout().setMargin(new MarginInfo(false, true));
233

    
234
        // typeDesignationsCollectionField.getLayout().setMargin(false);
235
        // typeDesignationsCollectionField.addStyleName("composite-field-wrapper");
236
        // addField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs", 0, row, 2, row);
237

    
238
        typeDesignationsScrollPanel = new Panel(typeDesignationsCollectionField.getLayout());
239
        typeDesignationsScrollPanel.setCaption("Types");
240
        typeDesignationsScrollPanel.setWidth(800, Unit.PIXELS);
241

    
242
        bindField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs");
243
        addComponent(typeDesignationsScrollPanel, 0, row, 2, row);
244

    
245
        row++;
246
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
247
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
248
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProber(RolesAndPermissions.ROLE_CURATION));
249
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
250
        if(isCurator || isAdmin){
251
            annotationsListField.withNewButton(true);
252
        } else {
253
            annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
254
        }
255
        addField(annotationsListField, "annotations", 0, row, 2, row);
256

    
257
     }
258

    
259

    
260
    /**
261
     * {@inheritDoc}
262
     */
263
    @Override
264
    public String getWindowCaption() {
265
        return "Specimen typedesignations editor";
266
    }
267

    
268
    /**
269
     * {@inheritDoc}
270
     */
271
    @Override
272
    public void focusFirst() {
273
        // none
274
    }
275

    
276
    /**
277
     * {@inheritDoc}
278
     */
279
    @Override
280
    protected String getDefaultComponentStyles() {
281
        return "tiny";
282
    }
283

    
284
    @Override
285
    public boolean allowAnonymousAccess() {
286
        return false;
287
    }
288

    
289
    @Override
290
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
291
        return null;
292
    }
293

    
294
    @Override
295
    public String getAccessDeniedMessage() {
296
        return accessDeniedMessage;
297
    }
298

    
299
    @Override
300
    public void setAccessDeniedMessage(String accessDeniedMessage) {
301
        this.accessDeniedMessage = accessDeniedMessage;
302
    }
303

    
304
    /**
305
     * {@inheritDoc}
306
     */
307
    @Override
308
    public boolean isResizable() {
309
        return true;
310
    }
311

    
312

    
313
    // ------- SpecimenTypeDesignationWorkingsetPopupEditorView methods ---- //
314
    @Override
315
    public ElementCollectionField<SpecimenTypeDesignationDTO> getTypeDesignationsCollectionField() {
316
        return typeDesignationsCollectionField;
317
    }
318

    
319
    @Override
320
    public void applyDefaultComponentStyle(Component ... components){
321
        for(int i = 0; i <components.length; i++){
322
            components[i].setStyleName(getDefaultComponentStyles());
323
        }
324
    }
325

    
326
    /**
327
     * {@inheritDoc}
328
     */
329
    @Override
330
    public void grantToCurrentUser(EnumSet<CRUD> crud) {
331
        getPresenter().setGrantsForCurrentUser(crud);
332

    
333
    }
334

    
335
    /**
336
     * {@inheritDoc}
337
     */
338
    @Override
339
    protected void afterItemDataSourceSet() {
340
        super.afterItemDataSourceSet();
341
        GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
342
        for(int rowIndex = 1; rowIndex < gridLayout.getRows(); rowIndex++){ // first row is header
343
            Component item = gridLayout.getComponent(SpecimenTypeDesignationDTORow.rowListSelectColumn(), rowIndex);
344
            ((CollectionRowRepresentative)item).updateRowItemsEnabledStates();
345
        }
346
        updateAllowDeleteTypeDesignation();
347
    }
348

    
349
    /**
350
     * {@inheritDoc}
351
     */
352
    @Override
353
    public void updateAllowDeleteTypeDesignation(){
354
        // disable the delete button if there is only one typeDesignation
355
        // if this typeDesignation is deleted the fieldUnit would become orphan in the
356
        // TypeDesignationWorkingSet
357
        GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
358
        if(gridLayout.getRows() == 3){ // first row is header, last row is next new item
359
            gridLayout.getComponent(gridLayout.getColumns() - 1, 1).setEnabled(false);
360
        }
361
    }
362

    
363

    
364
    /**
365
     * {@inheritDoc}
366
     */
367
    @Override
368
    public void setReadOnly(boolean readOnly) {
369
        super.setReadOnly(readOnly);
370
        getFieldLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
371
        collectorField.setEditorReadOnly(readOnly);
372
        typeDesignationsCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
373

    
374
    }
375

    
376
    /**
377
     * @return the collectorField
378
     */
379
    @Override
380
    public TeamOrPersonField getCollectorField() {
381
        return collectorField;
382
    }
383

    
384
    /**
385
     * By default  AnnotationType.EDITORIAL() is enabled.
386
     *
387
     * @return the editableAnotationTypes
388
     */
389
    @Override
390
    public AnnotationType[] getEditableAnotationTypes() {
391
        return editableAnotationTypes;
392
    }
393

    
394
    /**
395
     * By default  AnnotationType.EDITORIAL() is enabled.
396
     *
397
     *
398
     * @param editableAnotationTypes the editableAnotationTypes to set
399
     */
400
    @Override
401
    public void setEditableAnotationTypes(AnnotationType ... editableAnotationTypes) {
402
        this.editableAnotationTypes = editableAnotationTypes;
403
    }
404

    
405
    /**
406
     * {@inheritDoc}
407
     */
408
    @Override
409
    public FilterableAnnotationsField getAnnotationsField() {
410
        return annotationsListField;
411
    }
412

    
413
    @Override
414
    public GeoLocationField getExactLocationField() {
415
        return exactLocationField;
416
    }
417

    
418

    
419

    
420
}
(9-9/15)