Project

General

Profile

Download (14.8 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.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.NativeSelect;
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
 * TODO as subclass of AbstractCdmPopupEditor?
52
 *
53
 */
54
@SpringComponent
55
@Scope("prototype")
56
public class SpecimenTypeDesignationWorkingsetPopupEditor
57
    extends AbstractPopupEditor<SpecimenTypeDesignationWorkingSetDTO, SpecimenTypeDesignationWorkingsetEditorPresenter>
58
    implements SpecimenTypeDesignationWorkingsetPopupEditorView, AccessRestrictedView, PerEntityAuthorityGrantingEditor {
59
    /**
60
     *
61
     */
62
    private static final String CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING = "Can't save as long as type designations are missing.";
63

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

    
75
    private static final long serialVersionUID = 5418275817834009509L;
76

    
77
    private NativeSelect countrySelectField;
78

    
79
    private ElementCollectionField<SpecimenTypeDesignationDTO> typeDesignationsCollectionField;
80

    
81
    private EnumSet<CRUD> crud;
82

    
83
    private TeamOrPersonField collectorField;
84

    
85
    private FilterableAnnotationsField annotationsListField;
86

    
87
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
88

    
89
    private GeoLocationField exactLocationField;
90

    
91
    private Panel typeDesignationsScrollPanel;
92

    
93
    private String accessDeniedMessage;
94

    
95
    /**
96
     * @return the countrySelectField
97
     */
98
    @Override
99
    public NativeSelect getCountrySelectField() {
100
        return countrySelectField;
101
    }
102

    
103
    /**
104
     * {@inheritDoc}
105
     */
106
    @Override
107
    protected void initContent() {
108

    
109
        GridLayout grid = (GridLayout)getFieldLayout();
110
        grid.setSpacing(true);
111
        grid.setMargin(true);
112
        grid.setColumns(3);
113
        grid.setRows(10);
114

    
115
        //TODO typifyingAuthors
116

    
117
        // FieldUnit + GatheringEvent
118

    
119
        int row = 0;
120
        countrySelectField = new NativeSelect("Country");
121
        addField(countrySelectField, "country", 1, row , 2, row);
122
        countrySelectField.setWidth("100%");
123
        countrySelectField.setItemCaptionMode(ItemCaptionMode.PROPERTY);
124
        countrySelectField.setItemCaptionPropertyId("label");
125

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

    
134
        row++;
135
        exactLocationField = new GeoLocationField("Geo location");
136
        addField(exactLocationField, "exactLocation", 0, row, 2, row);
137
        exactLocationField.setWidth("100%");
138

    
139
        row++;
140
        MinMaxTextField absElevationMinMax = new MinMaxTextField("Altitude", "m");
141
        absElevationMinMax.setWidth("100%");
142
        absElevationMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
143
        grid.addComponent(absElevationMinMax, 0, row, 2, row);
144

    
145
        bindField(absElevationMinMax.getMinField(), "absoluteElevation");
146
        bindField(absElevationMinMax.getMaxField(), "absoluteElevationMax");
147
        bindField(absElevationMinMax.getTextField(), "absoluteElevationText");
148

    
149
        absElevationMinMax.getMaxField().setConverter(new IntegerConverter());
150
        absElevationMinMax.getMinField().setConverter(new IntegerConverter());
151

    
152
        row++;
153
        MinMaxTextField distanceToWaterSurfaceMinMax = new MinMaxTextField("Distance to water surface", "m");
154
        distanceToWaterSurfaceMinMax.setWidth("100%");
155
        distanceToWaterSurfaceMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
156
        grid.addComponent(distanceToWaterSurfaceMinMax, 0, row, 2, row);
157

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

    
166
        row++;
167
        MinMaxTextField distanceToGroundMinMax = new MinMaxTextField("Distance to substrate", "m");
168
        distanceToGroundMinMax.setWidth("100%");
169
        distanceToGroundMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
170
        grid.addComponent(distanceToGroundMinMax, 0, row, 2, row);
171

    
172
        bindField(distanceToGroundMinMax.getMinField(), "distanceToGround");
173
        bindField(distanceToGroundMinMax.getMaxField(), "distanceToGroundMax");
174
        bindField(distanceToGroundMinMax.getTextField(), "distanceToGroundText");
175
        distanceToGroundMinMax.getMaxField().setConverter(new DoubleConverter());
176
        distanceToGroundMinMax.getMinField().setConverter(new DoubleConverter());
177

    
178
        row++;
179
        collectorField = new TeamOrPersonField("Collector", TeamOrPersonBaseCaptionGenerator.CacheType.COLLECTOR_TITLE);
180
        addField(collectorField, "collector", 0, row, 2, row);
181

    
182
        row++;
183

    
184
        TimePeriodField collectionDateField = new TimePeriodField("Collection date");
185
        // collectionDateField.setInputPrompt("dd.mm.yyyy");
186
        addField(collectionDateField, "gatheringDate", 0, row, 1, row);
187
        addTextField("Field number", "fieldNumber", 2, row);
188

    
189

    
190
        row++;
191

    
192
        // FIXME: can we use the Grid instead?
193
        typeDesignationsCollectionField = new ElementCollectionField<SpecimenTypeDesignationDTO>(
194
                SpecimenTypeDesignationDTO.class,
195
                SpecimenTypeDesignationDTORow.class
196
                ){
197

    
198
                    @Override
199
                    public void commit() throws SourceException, InvalidValueException {
200
                        validate(); // validate always so that empty rows are recognized
201
                        super.commit();
202
                    }
203

    
204
                    @Override
205
                    public boolean isEmpty() {
206
                        Collection value = getValue();
207
                        return value == null || value.isEmpty() ;
208
                    }
209

    
210
                    @Override
211
                    public void setComponentError(ErrorMessage componentError) {
212
                        typeDesignationsScrollPanel.setComponentError(componentError);
213
                    }
214

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

    
223
        typeDesignationsCollectionField.setPropertyHeader("accessionNumber", "Access. num.");
224
        typeDesignationsCollectionField.setPropertyHeader("preferredStableUri", "Stable URI");
225
        typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReference", "Image reference");
226
        typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReferenceDetail", "Reference detail");
227
        typeDesignationsCollectionField.addElementAddedListener( e -> typeDesignationsCollectionField.setComponentError(null));
228

    
229
        // typeDesignationsCollectionField.getLayout().setMargin(false);
230
        // typeDesignationsCollectionField.addStyleName("composite-field-wrapper");
231
        // addField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs", 0, row, 2, row);
232

    
233
        typeDesignationsScrollPanel = new Panel(typeDesignationsCollectionField.getLayout());
234
        typeDesignationsScrollPanel.setCaption("Types");
235
        typeDesignationsScrollPanel.setWidth(800, Unit.PIXELS);
236

    
237
        bindField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs");
238
        addComponent(typeDesignationsScrollPanel, 0, row, 2, row);
239

    
240
        row++;
241
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
242
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
243
        annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
244
        addField(annotationsListField, "annotations", 0, row, 2, row);
245

    
246
     }
247

    
248

    
249
    /**
250
     * {@inheritDoc}
251
     */
252
    @Override
253
    public String getWindowCaption() {
254
        return "Specimen typedesignations editor";
255
    }
256

    
257
    /**
258
     * {@inheritDoc}
259
     */
260
    @Override
261
    public void focusFirst() {
262
        // none
263
    }
264

    
265
    /**
266
     * {@inheritDoc}
267
     */
268
    @Override
269
    protected String getDefaultComponentStyles() {
270
        return "tiny";
271
    }
272

    
273
    @Override
274
    public boolean allowAnonymousAccess() {
275
        return false;
276
    }
277

    
278
    @Override
279
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
280
        return null;
281
    }
282

    
283
    @Override
284
    public String getAccessDeniedMessage() {
285
        return accessDeniedMessage;
286
    }
287

    
288
    @Override
289
    public void setAccessDeniedMessage(String accessDeniedMessage) {
290
        this.accessDeniedMessage = accessDeniedMessage;
291
    }
292

    
293
    /**
294
     * {@inheritDoc}
295
     */
296
    @Override
297
    public boolean isResizable() {
298
        return true;
299
    }
300

    
301

    
302
    // ------- SpecimenTypeDesignationWorkingsetPopupEditorView methods ---- //
303
    @Override
304
    public ElementCollectionField<SpecimenTypeDesignationDTO> getTypeDesignationsCollectionField() {
305
        return typeDesignationsCollectionField;
306
    }
307

    
308
    @Override
309
    public void applyDefaultComponentStyle(Component ... components){
310
        for(int i = 0; i <components.length; i++){
311
            components[i].setStyleName(getDefaultComponentStyles());
312
        }
313
    }
314

    
315
    /**
316
     * {@inheritDoc}
317
     */
318
    @Override
319
    public void grantToCurrentUser(EnumSet<CRUD> crud) {
320
        getPresenter().setGrantsForCurrentUser(crud);
321

    
322
    }
323

    
324
    /**
325
     * {@inheritDoc}
326
     */
327
    @Override
328
    protected void afterItemDataSourceSet() {
329
        super.afterItemDataSourceSet();
330
        GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
331
        for(int rowIndex = 1; rowIndex < gridLayout.getRows(); rowIndex++){ // first row is header
332
            Component item = gridLayout.getComponent(SpecimenTypeDesignationDTORow.rowListSelectColumn(), rowIndex);
333
            ((CollectionRowRepresentative)item).updateRowItemsEnabledStates();
334
        }
335
        updateAllowDelete();
336
    }
337

    
338
    /**
339
     * {@inheritDoc}
340
     */
341
    @Override
342
    public void updateAllowDelete(){
343
        // disable the delete button if there is only one typeDesignation
344
        // if this typeDesignation is deleted the fieldUnit would become orphan in the
345
        // TypeDesignationWorkingSet
346
        GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
347
        if(gridLayout.getRows() == 3){ // first row is header, last row is next new item
348
            gridLayout.getComponent(gridLayout.getColumns() - 1, 1).setEnabled(false);
349
        }
350
    }
351

    
352

    
353
    /**
354
     * {@inheritDoc}
355
     */
356
    @Override
357
    public void setReadOnly(boolean readOnly) {
358
        super.setReadOnly(readOnly);
359
        getFieldLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
360
        collectorField.setEditorReadOnly(readOnly);
361
        typeDesignationsCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
362

    
363
    }
364

    
365
    /**
366
     * @return the collectorField
367
     */
368
    @Override
369
    public TeamOrPersonField getCollectorField() {
370
        return collectorField;
371
    }
372

    
373
    /**
374
     * By default  AnnotationType.EDITORIAL() is enabled.
375
     *
376
     * @return the editableAnotationTypes
377
     */
378
    @Override
379
    public AnnotationType[] getEditableAnotationTypes() {
380
        return editableAnotationTypes;
381
    }
382

    
383
    /**
384
     * By default  AnnotationType.EDITORIAL() is enabled.
385
     *
386
     *
387
     * @param editableAnotationTypes the editableAnotationTypes to set
388
     */
389
    @Override
390
    public void setEditableAnotationTypes(AnnotationType ... editableAnotationTypes) {
391
        this.editableAnotationTypes = editableAnotationTypes;
392
    }
393

    
394
    /**
395
     * {@inheritDoc}
396
     */
397
    @Override
398
    public FilterableAnnotationsField getAnnotationsField() {
399
        return annotationsListField;
400
    }
401

    
402
    @Override
403
    public GeoLocationField getExactLocationField() {
404
        return exactLocationField;
405
    }
406

    
407

    
408

    
409
}
(8-8/14)