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
.reference
;
11 import java
.util
.Arrays
;
12 import java
.util
.Collection
;
13 import java
.util
.EnumSet
;
14 import java
.util
.HashMap
;
15 import java
.util
.LinkedHashMap
;
19 import org
.apache
.log4j
.Logger
;
20 import org
.springframework
.context
.annotation
.Scope
;
21 import org
.springframework
.security
.core
.GrantedAuthority
;
23 import com
.vaadin
.spring
.annotation
.SpringComponent
;
24 import com
.vaadin
.ui
.AbstractField
;
25 import com
.vaadin
.ui
.Alignment
;
26 import com
.vaadin
.ui
.Component
;
27 import com
.vaadin
.ui
.Field
;
28 import com
.vaadin
.ui
.GridLayout
;
29 import com
.vaadin
.ui
.ListSelect
;
30 import com
.vaadin
.ui
.TextField
;
32 import eu
.etaxonomy
.cdm
.api
.utility
.RoleProber
;
33 import eu
.etaxonomy
.cdm
.model
.agent
.Institution
;
34 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
35 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
36 import eu
.etaxonomy
.cdm
.model
.reference
.ReferencePropertyDefinitions
;
37 import eu
.etaxonomy
.cdm
.model
.reference
.ReferencePropertyDefinitions
.UnimplemetedCaseException
;
38 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceType
;
39 import eu
.etaxonomy
.cdm
.service
.UserHelperAccess
;
40 import eu
.etaxonomy
.cdm
.vaadin
.component
.TextFieldNFix
;
41 import eu
.etaxonomy
.cdm
.vaadin
.component
.common
.FilterableAnnotationsField
;
42 import eu
.etaxonomy
.cdm
.vaadin
.component
.common
.TeamOrPersonField
;
43 import eu
.etaxonomy
.cdm
.vaadin
.component
.common
.VerbatimTimePeriodField
;
44 import eu
.etaxonomy
.cdm
.vaadin
.event
.InstitutionEditorAction
;
45 import eu
.etaxonomy
.cdm
.vaadin
.event
.ReferenceEditorAction
;
46 import eu
.etaxonomy
.cdm
.vaadin
.permission
.AccessRestrictedView
;
47 import eu
.etaxonomy
.cdm
.vaadin
.permission
.RolesAndPermissions
;
48 import eu
.etaxonomy
.cdm
.vaadin
.ui
.RegistrationUIDefaults
;
49 import eu
.etaxonomy
.cdm
.vaadin
.util
.CdmTitleCacheCaptionGenerator
;
50 import eu
.etaxonomy
.cdm
.vaadin
.util
.TeamOrPersonBaseCaptionGenerator
;
51 import eu
.etaxonomy
.cdm
.vaadin
.util
.converter
.DoiConverter
;
52 import eu
.etaxonomy
.cdm
.vaadin
.util
.converter
.UriConverter
;
53 import eu
.etaxonomy
.vaadin
.component
.SwitchableTextField
;
54 import eu
.etaxonomy
.vaadin
.component
.ToOneRelatedEntityCombobox
;
55 import eu
.etaxonomy
.vaadin
.event
.EditorActionType
;
56 import eu
.etaxonomy
.vaadin
.mvp
.AbstractCdmPopupEditor
;
57 import eu
.etaxonomy
.vaadin
.util
.PropertyIdPath
;
60 * @author a.kohlbecker
66 public class ReferencePopupEditor
extends AbstractCdmPopupEditor
<Reference
, ReferenceEditorPresenter
> implements ReferencePopupEditorView
, AccessRestrictedView
{
68 private static final long serialVersionUID
= -4347633563800758815L;
70 private static final Logger logger
= Logger
.getLogger(ReferencePopupEditor
.class);
72 private TextField titleField
;
74 private final static int GRID_COLS
= 4; // 12 would fits for 2,3, and 4 Components per row
76 private final static int GRID_ROWS
= 14;
78 private ListSelect typeSelect
;
80 private ToOneRelatedEntityCombobox
<Reference
> inReferenceCombobox
;
82 private TeamOrPersonField authorshipField
;
84 private ToOneRelatedEntityCombobox
<Institution
> institutionCombobox
;
85 private ToOneRelatedEntityCombobox
<Institution
> schoolCombobox
;
87 private FilterableAnnotationsField annotationsListField
;
89 private AnnotationType
[] editableAnotationTypes
= RegistrationUIDefaults
.EDITABLE_ANOTATION_TYPES
;
91 private EnumSet
<ReferenceType
> referenceTypes
= EnumSet
.allOf(ReferenceType
.class);
93 private static Map
<String
,String
> propertyNameLabelMap
= new HashMap
<>();
95 private int variableGridStartRow
;
97 private int variableGridLastRow
;
100 * Used to record the fields from the variable grid part in their original order.
102 private LinkedHashMap
<String
, Field
<?
>> adaptiveFields
= new LinkedHashMap
<>();
104 private VerbatimTimePeriodField datePublishedField
;
107 propertyNameLabelMap
.put("inReference", "In reference");
108 propertyNameLabelMap
.put("inJournal", "In journal");
109 propertyNameLabelMap
.put("inSeries", "In series");
110 propertyNameLabelMap
.put("inBook", "In book");
117 public ReferencePopupEditor() {
118 super(new GridLayout(GRID_COLS
, GRID_ROWS
), Reference
.class);
122 protected void initContent() {
123 GridLayout grid
= (GridLayout
)getFieldLayout();
124 grid
.setSpacing(true);
125 grid
.setMargin(true);
131 "protectedAbbrevTitleCache",
132 "nomenclaturallyRelevant",
154 datePublishedField
= new VerbatimTimePeriodField("Date published");
155 addField(datePublishedField
, "datePublished", 0, row
, 1, row
);
156 typeSelect
= new ListSelect("Reference type");
157 typeSelect
.addItems(referenceTypes
);
158 typeSelect
.setNullSelectionAllowed(false);
159 typeSelect
.setRows(1);
160 typeSelect
.addValueChangeListener(e
-> updateFieldVisibility((ReferenceType
)e
.getProperty().getValue()));
161 addField(typeSelect
, "type", GRID_COLS
- 1, row
);
162 grid
.setComponentAlignment(typeSelect
, Alignment
.TOP_RIGHT
);
165 SwitchableTextField titleCacheField
= addSwitchableTextField("Reference cache", "titleCache", "protectedTitleCache", 0, row
, GRID_COLS
-1, row
);
166 titleCacheField
.setWidth(100, Unit
.PERCENTAGE
);
169 SwitchableTextField abbrevTitleCacheField
= addSwitchableTextField("Abbrev. cache", "abbrevTitleCache", "protectedAbbrevTitleCache", 0, row
, GRID_COLS
-1, row
);
170 abbrevTitleCacheField
.setWidth(100, Unit
.PERCENTAGE
);
173 titleField
= addTextField("Title", "title", 0, row
, GRID_COLS
-1, row
);
174 titleField
.setWidth(100, Unit
.PERCENTAGE
);
176 addTextField("Nomenclatural title", "abbrevTitle", 0, row
, GRID_COLS
-1, row
).setWidth(100, Unit
.PERCENTAGE
);
179 authorshipField
= new TeamOrPersonField("Author(s)", TeamOrPersonBaseCaptionGenerator
.CacheType
.BIBLIOGRAPHIC_TITLE
);
180 authorshipField
.setWidth(100, Unit
.PERCENTAGE
);
181 addField(authorshipField
, "authorship", 0, row
, GRID_COLS
-1, row
);
184 inReferenceCombobox
= new ToOneRelatedEntityCombobox
<Reference
>("In-reference", Reference
.class);
185 inReferenceCombobox
.setWidth(100, Unit
.PERCENTAGE
);
186 inReferenceCombobox
.addClickListenerAddEntity(e
-> getViewEventBus().publish(this,
187 new ReferenceEditorAction(EditorActionType
.ADD
, e
.getButton(), inReferenceCombobox
, this)
189 inReferenceCombobox
.addClickListenerEditEntity(e
-> {
190 if(inReferenceCombobox
.getValue() != null){
191 getViewEventBus().publish(this,
192 new ReferenceEditorAction(
193 EditorActionType
.EDIT
,
194 inReferenceCombobox
.getValue().getUuid(),
201 addField(inReferenceCombobox
, "inReference", 0, row
, GRID_COLS
-1, row
);
203 institutionCombobox
= new ToOneRelatedEntityCombobox
<Institution
>("Institution", Institution
.class);
204 institutionCombobox
.getSelect().setCaptionGenerator(
205 new CdmTitleCacheCaptionGenerator
<Institution
>()
207 institutionCombobox
.setWidth(100, Unit
.PERCENTAGE
);
208 institutionCombobox
.addClickListenerAddEntity(e
-> getViewEventBus().publish(this,
209 new InstitutionEditorAction(EditorActionType
.ADD
, e
.getButton(), institutionCombobox
, this)
211 institutionCombobox
.addClickListenerEditEntity(e
-> {
212 if(institutionCombobox
.getValue() != null){
213 getViewEventBus().publish(this,
214 new InstitutionEditorAction(
215 EditorActionType
.EDIT
,
216 institutionCombobox
.getValue().getUuid(),
224 schoolCombobox
= new ToOneRelatedEntityCombobox
<Institution
>("School", Institution
.class);
225 schoolCombobox
.getSelect().setCaptionGenerator(
226 new CdmTitleCacheCaptionGenerator
<Institution
>()
228 schoolCombobox
.addClickListenerAddEntity(e
-> getViewEventBus().publish(this,
229 new InstitutionEditorAction(EditorActionType
.ADD
, e
.getButton(), schoolCombobox
, this)
231 schoolCombobox
.addClickListenerEditEntity(e
-> {
232 if(schoolCombobox
.getValue() != null){
233 getViewEventBus().publish(this,
234 new InstitutionEditorAction(
235 EditorActionType
.EDIT
,
236 schoolCombobox
.getValue().getUuid(),
244 addField(institutionCombobox
, "institution", 0, row
, GRID_COLS
-1, row
);
246 addField(schoolCombobox
, "school", 0, row
, GRID_COLS
-1, row
);
249 variableGridStartRow
= row
;
251 addTextField("Organization", "organization", 0, row
).setWidth(100, Unit
.PERCENTAGE
);
253 addTextField("Series", "seriesPart", 0, row
).setWidth(100, Unit
.PERCENTAGE
);
254 addTextField("Volume", "volume", 1, row
).setWidth(100, Unit
.PERCENTAGE
);
255 addTextField("Pages", "pages", 2, row
).setWidth(100, Unit
.PERCENTAGE
);
256 addTextField("Edition", "edition", 3, row
).setWidth(100, Unit
.PERCENTAGE
);
259 addTextField("Place published", "placePublished", 0, row
, 0, row
).setWidth(100, Unit
.PERCENTAGE
);
260 TextField publisherField
= addTextField("Publisher", "publisher", 1, row
, 1, row
);
261 publisherField
.setWidth(100, Unit
.PERCENTAGE
);
262 addTextField("Editor", "editor", 2, row
).setWidth(100, Unit
.PERCENTAGE
);
265 addTextField("ISSN", "issn", 0, row
).setWidth(100, Unit
.PERCENTAGE
);
266 addTextField("ISBN", "isbn", 1, row
).setWidth(100, Unit
.PERCENTAGE
);
267 TextFieldNFix doiField
= new TextFieldNFix("DOI");
268 doiField
.setConverter(new DoiConverter());
269 doiField
.setWidth(100, Unit
.PERCENTAGE
);
270 addField(doiField
, "doi", 2, row
);
271 TextFieldNFix uriField
= new TextFieldNFix("Uri");
272 uriField
.setConverter(new UriConverter());
273 uriField
.setWidth(100, Unit
.PERCENTAGE
);
274 addField(uriField
, "uri", 3, row
);
277 variableGridLastRow
= row
;
280 annotationsListField
= new FilterableAnnotationsField("Editorial notes");
281 annotationsListField
.setWidth(100, Unit
.PERCENTAGE
);
282 annotationsListField
.setAnnotationTypesVisible(editableAnotationTypes
);
283 addField(annotationsListField
, "annotations", 0, row
, GRID_COLS
-1, row
);
286 // titleField.setRequired(true);
287 // publisherField.setRequired(true);
289 setAdvancedModeEnabled(true);
290 registerAdvancedModeComponents(titleCacheField
, abbrevTitleCacheField
);
291 registerAdvancedModeComponents(authorshipField
.getCachFields());
292 setAdvancedMode(false);
300 private Object
updateFieldVisibility(ReferenceType referenceType
) {
302 GridLayout grid
= (GridLayout
)getFieldLayout();
304 initAdaptiveFields();
306 // clear the variable grid part
307 for(int row
= variableGridStartRow
; row
<= variableGridLastRow
; row
++){
308 for(int x
=0; x
< grid
.getColumns(); x
++){
309 grid
.removeComponent(x
, row
);
313 // set cursor at the beginning of the variable grid part
314 grid
.setCursorY(variableGridStartRow
);
317 // place the fields which are required for the given referenceType in the variable grid part while
318 // and retain the original order which is recorded in the adaptiveFields
320 Map
<String
, String
> fieldPropertyDefinition
= ReferencePropertyDefinitions
.fieldPropertyDefinition(referenceType
);
322 datePublishedField
.setVisible(fieldPropertyDefinition
.containsKey("datePublished"));
323 authorshipField
.setVisible(fieldPropertyDefinition
.containsKey("authorship"));
324 String inRefCaption
= fieldPropertyDefinition
.get("inReference");
325 inReferenceCombobox
.setVisible(inRefCaption
!= null);
326 if(inRefCaption
!= null){
327 inReferenceCombobox
.setCaption(propertyNameLabelMap
.get(inRefCaption
));
329 getField("title").setVisible(fieldPropertyDefinition
.containsKey("title"));
331 EnumSet
<ReferenceType
> hideNomTitle
= EnumSet
.of(ReferenceType
.Article
, ReferenceType
.Section
, ReferenceType
.BookSection
, ReferenceType
.InProceedings
);
332 getField("abbrevTitle").setVisible(!hideNomTitle
.contains(referenceType
));
333 institutionCombobox
.setVisible(fieldPropertyDefinition
.containsKey("institution"));
334 schoolCombobox
.setVisible(fieldPropertyDefinition
.containsKey("school"));
336 for(String fieldName
: adaptiveFields
.keySet()){ // iterate over the LinkedHashMap to retain the original order of the fields
337 if(fieldPropertyDefinition
.containsKey(fieldName
)){
338 Field
<?
> field
= adaptiveFields
.get(fieldName
);
339 grid
.addComponent(field
);
340 String propertyName
= fieldPropertyDefinition
.get(fieldName
);
341 if(propertyName
!= fieldName
){
342 field
.setCaption(propertyNameLabelMap
.get(propertyName
));
346 } catch (UnimplemetedCaseException e
) {
349 setAllFieldsVisible(true);
350 // fix inReference label
351 getField("inReference").setCaption(propertyNameLabelMap
.get("inReference"));
362 protected void initAdaptiveFields() {
363 GridLayout grid
= (GridLayout
)getFieldLayout();
364 // initialize the map of adaptive fields
365 if(adaptiveFields
.isEmpty()){
367 Map
<String
, String
> fieldPropertyDefinition
= ReferencePropertyDefinitions
.fieldPropertyDefinition(null);
368 Set
<String
> fieldNames
= fieldPropertyDefinition
.keySet();
369 for(int row
= variableGridStartRow
; row
<= variableGridLastRow
; row
++){
370 for(int x
=0; x
< grid
.getColumns(); x
++){
371 Component c
= grid
.getComponent(x
, row
);
372 logger
.trace("initAdaptiveFields() - y: " + row
+ " x: " + x
+ " component:" + (c
!= null ? c
.getClass().getSimpleName(): "NULL"));
373 if(c
!= null && c
instanceof Field
){
374 Field
<?
> field
= (Field
<?
>)c
;
375 PropertyIdPath propertyIdPath
= boundPropertyIdPath(field
);
376 logger
.trace("initAdaptiveFields() - " + field
.getCaption() + " -> " + propertyIdPath
);
377 if(propertyIdPath
!= null && fieldNames
.contains(propertyIdPath
.toString())){
378 adaptiveFields
.put(propertyIdPath
.toString(), field
);
383 } catch (UnimplemetedCaseException e
) {
384 throw new RuntimeException(e
);
389 protected void setAllFieldsVisible(boolean visible
){
390 GridLayout grid
= (GridLayout
)getFieldLayout();
391 for(Component c
: grid
){
392 if(AbstractField
.class.isAssignableFrom(c
.getClass())){
393 c
.setVisible(visible
);
400 public void setAdvancedMode(boolean isAdvancedMode
) {
401 boolean isCurator
= UserHelperAccess
.userHelper().userIs(new RoleProber(RolesAndPermissions
.ROLE_CURATION
));
402 boolean isAdmin
= UserHelperAccess
.userHelper().userIsAdmin();
404 boolean canEditAllCaches
= isAdmin
|| isCurator
;
405 super.setAdvancedMode(isAdvancedMode
);
406 if(!canEditAllCaches
){
407 advancedModeComponents
.forEach(c
-> c
.setReadOnly(true));
408 Arrays
.asList(authorshipField
.getCachFields()).forEach(c
-> c
.setReadOnly(false));
417 public String
getWindowCaption() {
418 return "Reference editor";
425 protected String
getDefaultComponentStyles() {
430 * {@inheritDoc} // TODO Auto-generated method stub
433 public void focusFirst() {
441 public boolean isResizable() {
449 public boolean allowAnonymousAccess() {
457 public Collection
<Collection
<GrantedAuthority
>> allowedGrantedAuthorities() {
462 public ListSelect
getTypeSelect() {
470 public ToOneRelatedEntityCombobox
<Reference
> getInReferenceCombobox() {
471 return inReferenceCombobox
;
478 public TeamOrPersonField
getAuthorshipField() {
479 return authorshipField
;
483 public FilterableAnnotationsField
getAnnotationsField() {
484 return annotationsListField
;
487 public void withReferenceTypes(EnumSet
<ReferenceType
> types
){
488 this.referenceTypes
= types
;
489 if(typeSelect
!= null){
490 typeSelect
.removeAllItems();
491 typeSelect
.addItems(referenceTypes
);
496 public ToOneRelatedEntityCombobox
<Institution
> getInstitutionCombobox() {
497 return institutionCombobox
;
501 public ToOneRelatedEntityCombobox
<Institution
> getSchoolCombobox() {
502 return schoolCombobox
;