Project

General

Profile

Download (15 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.RoleProberImpl;
31
import eu.etaxonomy.cdm.model.common.AnnotationType;
32
import eu.etaxonomy.cdm.model.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
    private static final String CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING = "Can't save as long as type designations are missing.";
65

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

    
77
    private static final long serialVersionUID = 5418275817834009509L;
78

    
79
    private NativeSelect countrySelectField;
80

    
81
    private ElementCollectionField<SpecimenTypeDesignationDTO> typeDesignationsCollectionField;
82

    
83
    private EnumSet<CRUD> crud;
84

    
85
    private TeamOrPersonField collectorField;
86

    
87
    private FilterableAnnotationsField annotationsListField;
88

    
89
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
90

    
91
    private GeoLocationField exactLocationField;
92

    
93
    private Panel typeDesignationsScrollPanel;
94

    
95
    private String accessDeniedMessage;
96

    
97

    
98
    @Override
99
    public NativeSelect getCountrySelectField() {
100
        return countrySelectField;
101
    }
102

    
103
    @Override
104
    protected void initContent() {
105

    
106
        GridLayout grid = (GridLayout)getFieldLayout();
107
        grid.setSpacing(true);
108
        grid.setMargin(true);
109
        grid.setColumns(3);
110
        grid.setRows(10);
111
        int endColumnIndex = 2;
112

    
113
        //TODO typifyingAuthors
114

    
115
        // FieldUnit + GatheringEvent
116

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

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

    
132
        row++;
133
        exactLocationField = new GeoLocationField("Geo location");
134
        addField(exactLocationField, "exactLocation", 0, row, endColumnIndex, row);
135
        exactLocationField.setWidth("100%");
136

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

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

    
147
        absElevationMinMax.getMaxField().setConverter(new IntegerConverter());
148
        absElevationMinMax.getMinField().setConverter(new IntegerConverter());
149

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

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

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

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

    
176
        row++;
177
        collectorField = new TeamOrPersonField("Collector", TeamOrPersonBaseCaptionGenerator.CacheType.COLLECTOR_TITLE);
178
        addField(collectorField, "collector", 0, row, endColumnIndex, row);
179

    
180
        row++;
181

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

    
187

    
188
        row++;
189

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

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

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

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

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

    
221
        typeDesignationsCollectionField.setPropertyHeader("accessionNumber", "Access. num.");
222
        typeDesignationsCollectionField.setPropertyHeader("preferredStableUri", "Stable URI");
223
        typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReference", "Image reference");
224
        typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReferenceDetail", "Reference detail");
225
        typeDesignationsCollectionField.addElementAddedListener( e -> typeDesignationsCollectionField.setComponentError(null));
226
        typeDesignationsCollectionField.getLayout().setMargin(new MarginInfo(false, true));
227

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

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

    
236
        bindField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs");
237
        addComponent(typeDesignationsScrollPanel, 0, row, endColumnIndex, row);
238

    
239
        row++;
240
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
241
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
242
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProberImpl(RolesAndPermissions.ROLE_CURATION));
243
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
244
        if(isCurator || isAdmin){
245
            annotationsListField.withNewButton(true);
246
        } else {
247
            annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
248
        }
249
        addField(annotationsListField, "annotations", 0, row, endColumnIndex, row);
250

    
251
     }
252

    
253
    @Override
254
    public String getWindowCaption() {
255
        return "Specimen typedesignations editor";
256
    }
257

    
258
    @Override
259
    public void focusFirst() {
260
        // none
261
    }
262

    
263
    @Override
264
    protected String getDefaultComponentStyles() {
265
        return "tiny";
266
    }
267

    
268
    @Override
269
    public boolean allowAnonymousAccess() {
270
        return false;
271
    }
272

    
273
    @Override
274
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
275
        return null;
276
    }
277

    
278
    @Override
279
    public String getAccessDeniedMessage() {
280
        return accessDeniedMessage;
281
    }
282

    
283
    @Override
284
    public void setAccessDeniedMessage(String accessDeniedMessage) {
285
        this.accessDeniedMessage = accessDeniedMessage;
286
    }
287

    
288
    @Override
289
    public boolean isResizable() {
290
        return true;
291
    }
292

    
293

    
294
    // ------- SpecimenTypeDesignationWorkingsetPopupEditorView methods ---- //
295
    @Override
296
    public ElementCollectionField<SpecimenTypeDesignationDTO> getTypeDesignationsCollectionField() {
297
        return typeDesignationsCollectionField;
298
    }
299

    
300
    @Override
301
    public void applyDefaultComponentStyle(Component ... components){
302
        for(int i = 0; i <components.length; i++){
303
            components[i].setStyleName(getDefaultComponentStyles());
304
        }
305
    }
306

    
307
    @Override
308
    public void grantToCurrentUser(EnumSet<CRUD> crud) {
309
        getPresenter().setGrantsForCurrentUser(crud);
310

    
311
    }
312

    
313
    @Override
314
    protected void afterItemDataSourceSet() {
315
        super.afterItemDataSourceSet();
316
        GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
317
        for(int rowIndex = 1; rowIndex < gridLayout.getRows(); rowIndex++){ // first row is header
318
            Component item = gridLayout.getComponent(SpecimenTypeDesignationDTORow.rowListSelectColumn(), rowIndex);
319
            ((CollectionRowRepresentative)item).updateRowItemsEnabledStates();
320
        }
321
        updateAllowDeleteTypeDesignation();
322
    }
323

    
324
    @Override
325
    public void updateAllowDeleteTypeDesignation(){
326
        // disable the delete button if there is only one typeDesignation
327
        // if this typeDesignation is deleted the fieldUnit would become orphan in the
328
        // TypeDesignationWorkingSet
329
        GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
330
        if(gridLayout.getRows() == 3){ // first row is header, last row is next new item
331
            gridLayout.getComponent(gridLayout.getColumns() - 1, 1).setEnabled(false);
332
        }
333
    }
334

    
335
    @Override
336
    public void setReadOnly(boolean readOnly) {
337
        super.setReadOnly(readOnly);
338
        getFieldLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
339
        collectorField.setEditorReadOnly(readOnly);
340
        typeDesignationsCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
341

    
342
    }
343

    
344
    @Override
345
    public TeamOrPersonField getCollectorField() {
346
        return collectorField;
347
    }
348

    
349
    /**
350
     * By default  AnnotationType.EDITORIAL() is enabled.
351
     */
352
    @Override
353
    public AnnotationType[] getEditableAnotationTypes() {
354
        return editableAnotationTypes;
355
    }
356

    
357
    /**
358
     * By default  AnnotationType.EDITORIAL() is enabled.
359
     *
360
     * @param editableAnotationTypes the editableAnotationTypes to set
361
     */
362
    @Override
363
    public void setEditableAnotationTypes(AnnotationType ... editableAnotationTypes) {
364
        this.editableAnotationTypes = editableAnotationTypes;
365
    }
366

    
367

    
368
    @Override
369
    public FilterableAnnotationsField getAnnotationsField() {
370
        return annotationsListField;
371
    }
372

    
373
    @Override
374
    public GeoLocationField getExactLocationField() {
375
        return exactLocationField;
376
    }
377

    
378

    
379
}
(12-12/18)