2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.vaadin
.view
.name
;
11 import java
.util
.Collection
;
12 import java
.util
.EnumSet
;
14 import org
.springframework
.context
.annotation
.Scope
;
15 import org
.springframework
.security
.core
.GrantedAuthority
;
16 import org
.vaadin
.viritin
.fields
.ElementCollectionField
;
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
;
30 import eu
.etaxonomy
.cdm
.api
.util
.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
.SpecimenTypeDesignationSetDTO
;
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
;
52 * @author a.kohlbecker
55 * TODO as subclass of AbstractCdmPopupEditor?
59 public class SpecimenTypeDesignationSetPopupEditor
60 extends AbstractPopupEditor
<SpecimenTypeDesignationSetDTO
, SpecimenTypeDesignationSetEditorPresenter
, SpecimenTypeDesignationSetPopupEditorView
>
61 implements SpecimenTypeDesignationSetPopupEditorView
, AccessRestrictedView
, PerEntityAuthorityGrantingEditor
{
63 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 public SpecimenTypeDesignationSetPopupEditor() {
66 super(new GridLayout(), SpecimenTypeDesignationSetDTO
.class);
67 GridLayout grid
= (GridLayout
) getFieldLayout();
69 grid
.setSpacing(true);
72 private static final long serialVersionUID
= 5418275817834009509L;
74 private NativeSelect countrySelectField
;
76 private ElementCollectionField
<SpecimenTypeDesignationDTO
> typeDesignationsCollectionField
;
78 private TeamOrPersonField collectorField
;
80 private FilterableAnnotationsField annotationsListField
;
82 private AnnotationType
[] editableAnotationTypes
= RegistrationUIDefaults
.EDITABLE_ANOTATION_TYPES
;
84 private GeoLocationField exactLocationField
;
86 private Panel typeDesignationsScrollPanel
;
88 private String accessDeniedMessage
;
92 public NativeSelect
getCountrySelectField() {
93 return countrySelectField
;
97 protected void initContent() {
99 GridLayout grid
= (GridLayout
)getFieldLayout();
100 grid
.setSpacing(true);
101 grid
.setMargin(true);
104 int endColumnIndex
= 2;
106 //TODO typifyingAuthors
108 // FieldUnit + GatheringEvent
111 countrySelectField
= new NativeSelect("Country");
112 addField(countrySelectField
, "country", 1, row
, endColumnIndex
, row
);
113 countrySelectField
.setWidth("100%");
114 countrySelectField
.setItemCaptionMode(ItemCaptionMode
.PROPERTY
);
115 countrySelectField
.setItemCaptionPropertyId("label");
118 TextArea localityField
= new TextArea("Locality");
119 localityField
.setNullRepresentation("");
120 addField(localityField
, "locality", 0, row
, endColumnIndex
, row
);
121 localityField
.setWidth("100%");
122 // NOTE: setRows and SetCold breaks he width setting,
123 // see https://github.com/vaadin/framework/issues/3617
126 exactLocationField
= new GeoLocationField("Geo location");
127 addField(exactLocationField
, "exactLocation", 0, row
, endColumnIndex
, row
);
128 exactLocationField
.setWidth("100%");
131 MinMaxTextField absElevationMinMax
= new MinMaxTextField("Altitude", "m");
132 absElevationMinMax
.setWidth("100%");
133 absElevationMinMax
.addSubComponentsStyleName(getDefaultComponentStyles());
134 grid
.addComponent(absElevationMinMax
, 0, row
, endColumnIndex
, row
);
136 bindField(absElevationMinMax
.getMinField(), "absoluteElevation");
137 bindField(absElevationMinMax
.getMaxField(), "absoluteElevationMax");
138 bindField(absElevationMinMax
.getTextField(), "absoluteElevationText");
140 absElevationMinMax
.getMaxField().setConverter(new IntegerConverter());
141 absElevationMinMax
.getMinField().setConverter(new IntegerConverter());
144 MinMaxTextField distanceToWaterSurfaceMinMax
= new MinMaxTextField("Distance to water surface", "m");
145 distanceToWaterSurfaceMinMax
.setWidth("100%");
146 distanceToWaterSurfaceMinMax
.addSubComponentsStyleName(getDefaultComponentStyles());
147 grid
.addComponent(distanceToWaterSurfaceMinMax
, 0, row
, endColumnIndex
, row
);
149 bindField(distanceToWaterSurfaceMinMax
.getMinField(), "distanceToWaterSurface");
150 bindField(distanceToWaterSurfaceMinMax
.getMaxField(), "distanceToWaterSurfaceMax");
151 bindField(distanceToWaterSurfaceMinMax
.getTextField(), "distanceToWaterSurfaceText");
152 distanceToWaterSurfaceMinMax
.getMaxField().setConverter(new DoubleConverter());
153 distanceToWaterSurfaceMinMax
.getMinField().setConverter(new DoubleConverter());
154 distanceToWaterSurfaceMinMax
.getMaxField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double
.MAX_VALUE
));
155 distanceToWaterSurfaceMinMax
.getMinField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double
.MAX_VALUE
));
158 MinMaxTextField distanceToGroundMinMax
= new MinMaxTextField("Distance to substrate", "m");
159 distanceToGroundMinMax
.setWidth("100%");
160 distanceToGroundMinMax
.addSubComponentsStyleName(getDefaultComponentStyles());
161 grid
.addComponent(distanceToGroundMinMax
, 0, row
, endColumnIndex
, row
);
163 bindField(distanceToGroundMinMax
.getMinField(), "distanceToGround");
164 bindField(distanceToGroundMinMax
.getMaxField(), "distanceToGroundMax");
165 bindField(distanceToGroundMinMax
.getTextField(), "distanceToGroundText");
166 distanceToGroundMinMax
.getMaxField().setConverter(new DoubleConverter());
167 distanceToGroundMinMax
.getMinField().setConverter(new DoubleConverter());
170 collectorField
= new TeamOrPersonField("Collector", TeamOrPersonBaseCaptionGenerator
.CacheType
.COLLECTOR_TITLE
);
171 addField(collectorField
, "collector", 0, row
, endColumnIndex
, row
);
175 TimePeriodField collectionDateField
= new TimePeriodField("Collection date");
176 // collectionDateField.setInputPrompt("dd.mm.yyyy");
177 addField(collectionDateField
, "gatheringDate", 0, row
, 1, row
);
178 addTextField("Field number", "fieldNumber", endColumnIndex
, row
);
183 // FIXME: can we use the Grid instead?
184 typeDesignationsCollectionField
= new ElementCollectionField
<SpecimenTypeDesignationDTO
>(
185 SpecimenTypeDesignationDTO
.class,
186 SpecimenTypeDesignationDTORow
.class
190 public void commit() throws SourceException
, InvalidValueException
{
191 validate(); // validate always so that empty rows are recognized
196 public boolean isEmpty() {
197 Collection value
= getValue();
198 return value
== null || value
.isEmpty() ;
202 public void setComponentError(ErrorMessage componentError
) {
203 typeDesignationsScrollPanel
.setComponentError(componentError
);
207 typeDesignationsCollectionField
.withCaption("Types");
208 typeDesignationsCollectionField
.getLayout().setSpacing(false);
209 typeDesignationsCollectionField
.getLayout().setColumns(3);
210 typeDesignationsCollectionField
.setRequired(true); // only works with the above overwritten commit()
211 typeDesignationsCollectionField
.setRequiredError(CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING
);
212 typeDesignationsCollectionField
.setVisibleProperties(SpecimenTypeDesignationDTORow
.visibleFields());
214 typeDesignationsCollectionField
.setPropertyHeader("accessionNumber", "Access. num.");
215 typeDesignationsCollectionField
.setPropertyHeader("preferredStableUri", "Stable URI");
216 typeDesignationsCollectionField
.setPropertyHeader("mediaSpecimenReference", "Image reference");
217 typeDesignationsCollectionField
.setPropertyHeader("mediaSpecimenReferenceDetail", "Reference detail");
218 typeDesignationsCollectionField
.addElementAddedListener( e
-> typeDesignationsCollectionField
.setComponentError(null));
219 typeDesignationsCollectionField
.getLayout().setMargin(new MarginInfo(false, true));
221 // typeDesignationsCollectionField.getLayout().setMargin(false);
222 // typeDesignationsCollectionField.addStyleName("composite-field-wrapper");
223 // addField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs", 0, row, 2, row);
225 typeDesignationsScrollPanel
= new Panel(typeDesignationsCollectionField
.getLayout());
226 typeDesignationsScrollPanel
.setCaption("Types");
227 typeDesignationsScrollPanel
.setWidth(800, Unit
.PIXELS
);
229 bindField(typeDesignationsCollectionField
, "specimenTypeDesignationDTOs");
230 addComponent(typeDesignationsScrollPanel
, 0, row
, endColumnIndex
, row
);
233 annotationsListField
= new FilterableAnnotationsField("Editorial notes");
234 annotationsListField
.setWidth(100, Unit
.PERCENTAGE
);
235 boolean isCurator
= UserHelperAccess
.userHelper().userIs(new RoleProberImpl(RolesAndPermissions
.ROLE_CURATION
));
236 boolean isAdmin
= UserHelperAccess
.userHelper().userIsAdmin();
237 if(isCurator
|| isAdmin
){
238 annotationsListField
.withNewButton(true);
240 annotationsListField
.setAnnotationTypesVisible(editableAnotationTypes
);
242 addField(annotationsListField
, "annotations", 0, row
, endColumnIndex
, row
);
247 public String
getWindowCaption() {
248 return "Specimen typedesignations editor";
252 public void focusFirst() {
257 protected String
getDefaultComponentStyles() {
262 public boolean allowAnonymousAccess() {
267 public Collection
<Collection
<GrantedAuthority
>> allowedGrantedAuthorities() {
272 public String
getAccessDeniedMessage() {
273 return accessDeniedMessage
;
277 public void setAccessDeniedMessage(String accessDeniedMessage
) {
278 this.accessDeniedMessage
= accessDeniedMessage
;
282 public boolean isResizable() {
287 // ------- SpecimenTypeDesignationSetPopupEditorView methods ---- //
289 public ElementCollectionField
<SpecimenTypeDesignationDTO
> getTypeDesignationsCollectionField() {
290 return typeDesignationsCollectionField
;
294 public void applyDefaultComponentStyle(Component
... components
){
295 for(int i
= 0; i
<components
.length
; i
++){
296 components
[i
].setStyleName(getDefaultComponentStyles());
301 public void grantToCurrentUser(EnumSet
<CRUD
> crud
) {
302 getPresenter().setGrantsForCurrentUser(crud
);
307 protected void afterItemDataSourceSet() {
308 super.afterItemDataSourceSet();
309 GridLayout gridLayout
= this.typeDesignationsCollectionField
.getLayout();
310 for(int rowIndex
= 1; rowIndex
< gridLayout
.getRows(); rowIndex
++){ // first row is header
311 Component item
= gridLayout
.getComponent(SpecimenTypeDesignationDTORow
.rowListSelectColumn(), rowIndex
);
312 ((CollectionRowRepresentative
)item
).updateRowItemsEnabledStates();
314 updateAllowDeleteTypeDesignation();
318 public void updateAllowDeleteTypeDesignation(){
319 // disable the delete button if there is only one typeDesignation
320 // if this typeDesignation is deleted the fieldUnit would become orphan in the
321 // TypeDesignationGroup
322 GridLayout gridLayout
= this.typeDesignationsCollectionField
.getLayout();
323 if(gridLayout
.getRows() == 3){ // first row is header, last row is next new item
324 gridLayout
.getComponent(gridLayout
.getColumns() - 1, 1).setEnabled(false);
329 public void setReadOnly(boolean readOnly
) {
330 super.setReadOnly(readOnly
);
331 getFieldLayout().iterator().forEachRemaining(c
-> c
.setReadOnly(readOnly
));
332 collectorField
.setEditorReadOnly(readOnly
);
333 typeDesignationsCollectionField
.getLayout().iterator().forEachRemaining(c
-> c
.setReadOnly(readOnly
));
337 public TeamOrPersonField
getCollectorField() {
338 return collectorField
;
342 * By default AnnotationType.EDITORIAL() is enabled.
345 public AnnotationType
[] getEditableAnotationTypes() {
346 return editableAnotationTypes
;
350 * By default AnnotationType.EDITORIAL() is enabled.
352 * @param editableAnotationTypes the editableAnotationTypes to set
355 public void setEditableAnotationTypes(AnnotationType
... editableAnotationTypes
) {
356 this.editableAnotationTypes
= editableAnotationTypes
;
361 public FilterableAnnotationsField
getAnnotationsField() {
362 return annotationsListField
;
366 public GeoLocationField
getExactLocationField() {
367 return exactLocationField
;