Project

General

Profile

Download (20 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.reference;
10

    
11
import java.util.Arrays;
12
import java.util.EnumSet;
13
import java.util.HashMap;
14
import java.util.LinkedHashMap;
15
import java.util.Map;
16
import java.util.Set;
17

    
18
import org.apache.logging.log4j.LogManager;
19
import org.apache.logging.log4j.Logger;
20
import org.springframework.context.annotation.Scope;
21

    
22
import com.vaadin.spring.annotation.SpringComponent;
23
import com.vaadin.ui.AbstractField;
24
import com.vaadin.ui.Alignment;
25
import com.vaadin.ui.Component;
26
import com.vaadin.ui.Field;
27
import com.vaadin.ui.GridLayout;
28
import com.vaadin.ui.Label;
29
import com.vaadin.ui.NativeSelect;
30
import com.vaadin.ui.TextField;
31

    
32
import eu.etaxonomy.cdm.api.util.RoleProberImpl;
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.data.validator.InReferenceTypeValidator;
45
import eu.etaxonomy.cdm.vaadin.data.validator.TimePeriodCompletenesValidator;
46
import eu.etaxonomy.cdm.vaadin.event.InstitutionEditorAction;
47
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
48
import eu.etaxonomy.cdm.vaadin.permission.RolesAndPermissions;
49
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
50
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
51
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
52
import eu.etaxonomy.cdm.vaadin.util.converter.DoiConverter;
53
import eu.etaxonomy.cdm.vaadin.util.converter.UriConverter;
54
import eu.etaxonomy.vaadin.component.SwitchableTextField;
55
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
56
import eu.etaxonomy.vaadin.event.EditorActionType;
57
import eu.etaxonomy.vaadin.mvp.AbstractCdmPopupEditor;
58
import eu.etaxonomy.vaadin.util.PropertyIdPath;
59

    
60
/**
61
 * @author a.kohlbecker
62
 * @since Apr 4, 2017
63
 *
64
 */
65
@SpringComponent
66
@Scope("prototype")
67
public class ReferencePopupEditor extends AbstractCdmPopupEditor<Reference, ReferenceEditorPresenter> implements ReferencePopupEditorView {
68

    
69
    private static final long serialVersionUID = -4347633563800758815L;
70

    
71
    private final static Logger logger = LogManager.getLogger();
72

    
73
    private TextField titleField;
74

    
75
    private final static int GRID_COLS = 4; // 12 would fit for 2,3, and 4 Components per row
76

    
77
    private final static int GRID_ROWS = 14;
78

    
79
    private final static int COL_FIELD_WIDTH_PX = 160;
80

    
81
    private final static String COL_FIELD_WIDTH_STR = COL_FIELD_WIDTH_PX + "px";
82

    
83
    private NativeSelect typeSelect;
84

    
85
    private ToOneRelatedEntityCombobox<Reference> inReferenceCombobox;
86

    
87
    private TeamOrPersonField authorshipField;
88

    
89
    private ToOneRelatedEntityCombobox<Institution> institutionCombobox;
90
    private ToOneRelatedEntityCombobox<Institution> schoolCombobox;
91

    
92
    private FilterableAnnotationsField annotationsListField;
93

    
94
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
95

    
96
    private EnumSet<ReferenceType> referenceTypes = EnumSet.allOf(ReferenceType.class);
97

    
98
    private static Map<String,String> propertyNameLabelMap = new HashMap<>();
99

    
100
    private int variableGridStartRow;
101

    
102
    private int variableGridLastRow;
103

    
104
    /**
105
     * Used to record the fields from the variable grid part in their original order.
106
     */
107
    private LinkedHashMap<String, Field<?>> adaptiveFields = new LinkedHashMap<>();
108

    
109
    private VerbatimTimePeriodField datePublishedField;
110

    
111
    static {
112
        propertyNameLabelMap.put("inReference", "In reference");
113
        propertyNameLabelMap.put("inProceedings", "In proceedings");
114
        propertyNameLabelMap.put("inJournal", "In journal");
115
        propertyNameLabelMap.put("inSeries", "In series");
116
        propertyNameLabelMap.put("inBook", "In book");
117
    }
118

    
119
    /**
120
     * @param layout
121
     * @param dtoType
122
     */
123
    public ReferencePopupEditor() {
124
        super(new GridLayout(GRID_COLS, GRID_ROWS), Reference.class);
125
    }
126

    
127
    @Override
128
    protected void initContent() {
129
        GridLayout grid = (GridLayout)getFieldLayout();
130
        grid.setSpacing(true);
131
        grid.setMargin(true);
132

    
133

    
134
        /*
135
        "type",
136
        "uri",
137
        "abbrevTitleCache",
138
        "protectedAbbrevTitleCache",
139
        "nomenclaturallyRelevant",
140
        "authorship",
141
        "referenceAbstract",
142
        "title",
143
        "abbrevTitle",
144
        "editor",
145
        "volume",
146
        "pages",
147
        "edition",
148
        "isbn",
149
        "issn",
150
        "doi",
151
        "seriesPart",
152
        "datePublished",
153
        "publisher",
154
        "placePublished",
155
        "institution",
156
        "school",
157
        "organization",
158
        "inReference"
159
         */
160
        int row = 0;
161
        datePublishedField = new VerbatimTimePeriodField("Date published");
162
        datePublishedField.addValidator(new TimePeriodCompletenesValidator());
163
        addField(datePublishedField, "datePublished", 0, row, 1, row);
164
        typeSelect = new NativeSelect("Reference type");
165
        typeSelect.addItems(referenceTypes);
166
        typeSelect.setNullSelectionAllowed(false);
167

    
168
        typeSelect.addValueChangeListener(e -> updateFieldVisibility((ReferenceType)e.getProperty().getValue()));
169
        addField(typeSelect, "type", GRID_COLS - 1, row);
170
        grid.setComponentAlignment(typeSelect, Alignment.TOP_RIGHT);
171
        row++;
172

    
173
        SwitchableTextField titleCacheField = addSwitchableTextField("Reference cache", "titleCache", "protectedTitleCache", 0, row, GRID_COLS-1, row);
174
        titleCacheField.setWidth(100, Unit.PERCENTAGE);
175
        row++;
176

    
177
        SwitchableTextField abbrevTitleCacheField = addSwitchableTextField("Abbrev. cache", "abbrevTitleCache", "protectedAbbrevTitleCache", 0, row, GRID_COLS-1, row);
178
        abbrevTitleCacheField.setWidth(100, Unit.PERCENTAGE);
179
        row++;
180

    
181
        titleField = addTextField("Title", "title", 0, row, GRID_COLS-1, row);
182
        titleField.setWidth(100, Unit.PERCENTAGE);
183
        row++;
184
        addTextField("Nomenclatural title", "abbrevTitle", 0, row, GRID_COLS-1, row).setWidth(100, Unit.PERCENTAGE);
185
        row++;
186

    
187
        authorshipField = new TeamOrPersonField("Author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.BIBLIOGRAPHIC_TITLE);
188
        authorshipField.setWidth(100,  Unit.PERCENTAGE);
189
        addField(authorshipField, "authorship", 0, row, GRID_COLS -1, row);
190
        row++;
191

    
192
        inReferenceCombobox = new ToOneRelatedEntityCombobox<Reference>("In-reference", Reference.class);
193
        inReferenceCombobox.setWidth(100, Unit.PERCENTAGE);
194
        inReferenceCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(this,
195
                new ReferenceEditorAction(EditorActionType.ADD, e.getButton(), inReferenceCombobox, this)
196
                ));
197
        inReferenceCombobox.addClickListenerEditEntity(e -> {
198
            if(inReferenceCombobox.getValue() != null){
199
                getViewEventBus().publish(this,
200
                    new ReferenceEditorAction(
201
                            EditorActionType.EDIT,
202
                            inReferenceCombobox.getValue().getUuid(),
203
                            e.getButton(),
204
                            inReferenceCombobox,
205
                            this)
206
                );
207
            }
208
            });
209
        addField(inReferenceCombobox, "inReference", 0, row, GRID_COLS -1, row);
210

    
211
        institutionCombobox = new ToOneRelatedEntityCombobox<Institution>("Institution", Institution.class);
212
        institutionCombobox.getSelect().setCaptionGenerator(
213
                new CdmTitleCacheCaptionGenerator<Institution>()
214
                );
215
        institutionCombobox.setWidth(100, Unit.PERCENTAGE);
216
        institutionCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(this,
217
                new InstitutionEditorAction(EditorActionType.ADD, e.getButton(), institutionCombobox, this)
218
                ));
219
        institutionCombobox.addClickListenerEditEntity(e -> {
220
            if(institutionCombobox.getValue() != null){
221
                getViewEventBus().publish(this,
222
                    new InstitutionEditorAction(
223
                            EditorActionType.EDIT,
224
                            institutionCombobox.getValue().getUuid(),
225
                            e.getButton(),
226
                            institutionCombobox,
227
                            this)
228
                );
229
            }
230
         });
231

    
232
        schoolCombobox = new ToOneRelatedEntityCombobox<Institution>("School", Institution.class);
233
        schoolCombobox.getSelect().setCaptionGenerator(
234
                new CdmTitleCacheCaptionGenerator<Institution>()
235
                );
236
        schoolCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(this,
237
                new InstitutionEditorAction(EditorActionType.ADD, e.getButton(), schoolCombobox, this)
238
                ));
239
        schoolCombobox.addClickListenerEditEntity(e -> {
240
            if(schoolCombobox.getValue() != null){
241
                getViewEventBus().publish(this,
242
                    new InstitutionEditorAction(
243
                            EditorActionType.EDIT,
244
                            schoolCombobox.getValue().getUuid(),
245
                            e.getButton(),
246
                            schoolCombobox,
247
                            this)
248
                );
249
            }
250
         });
251
        row++;
252
        addField(institutionCombobox, "institution", 0, row, GRID_COLS -1, row);
253
        row++;
254
        addField(schoolCombobox, "school", 0, row, GRID_COLS -1, row);
255
        row++;
256

    
257
        variableGridStartRow = row;
258

    
259
        addTextField("Organization", "organization", 0, row).setWidth(COL_FIELD_WIDTH_STR);
260
        row++;
261
        addTextField("Series", "seriesPart", 0, row).setWidth(COL_FIELD_WIDTH_STR);
262
        addTextField("Volume", "volume", 1, row).setWidth(COL_FIELD_WIDTH_STR);
263
        addTextField("Pages", "pages", 2, row).setWidth(COL_FIELD_WIDTH_STR);
264
        addTextField("Edition", "edition", 3, row).setWidth(COL_FIELD_WIDTH_STR);
265
        row++;
266

    
267
        addTextField("Place published", "placePublished", 0, row, 0, row).setWidth(COL_FIELD_WIDTH_STR);
268
        TextField publisherField = addTextField("Publisher", "publisher", 1, row, 1, row);
269
        publisherField.setWidth(COL_FIELD_WIDTH_STR);
270
        addTextField("Editor", "editor", 2, row).setWidth(COL_FIELD_WIDTH_STR);
271
        row++;
272

    
273
        addTextField("ISSN", "issn", 0, row).setWidth(COL_FIELD_WIDTH_STR);
274
        addTextField("ISBN", "isbn", 1, row).setWidth(COL_FIELD_WIDTH_STR);
275
        TextFieldNFix doiField = new TextFieldNFix("DOI");
276
        doiField.setConverter(new DoiConverter());
277
        doiField.setWidth(COL_FIELD_WIDTH_STR);
278
        addField(doiField, "doi", 2, row);
279
        TextFieldNFix uriField = new TextFieldNFix("Uri");
280
        uriField.setConverter(new UriConverter());
281
        uriField.setWidth(COL_FIELD_WIDTH_STR);
282
        addField(uriField, "uri", 3, row);
283

    
284

    
285
        variableGridLastRow = row;
286

    
287
        row++;
288
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
289
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
290
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProberImpl(RolesAndPermissions.ROLE_CURATION));
291
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
292
        if(isCurator || isAdmin){
293
            annotationsListField.withNewButton(true);
294
        } else {
295
            annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
296
        }
297
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
298

    
299

    
300
//        titleField.setRequired(true);
301
//        publisherField.setRequired(true);
302

    
303
        setAdvancedModeEnabled(true);
304
        registerAdvancedModeComponents(titleCacheField, abbrevTitleCacheField);
305
        registerAdvancedModeComponents(authorshipField.getCachFields());
306
        setAdvancedMode(false);
307

    
308
    }
309

    
310

    
311

    
312
    @Override
313
    protected void afterItemDataSourceSet() {
314
        super.afterItemDataSourceSet();
315
        inReferenceCombobox.getSelect().addValidator(new InReferenceTypeValidator(typeSelect));
316
    }
317

    
318
    /**
319
     * @param value
320
     * @return
321
     */
322
    private Object updateFieldVisibility(ReferenceType referenceType) {
323

    
324
        GridLayout grid = (GridLayout)getFieldLayout();
325

    
326
        initAdaptiveFields();
327

    
328
        // clear the variable grid part
329
        for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
330
            for(int x=0; x < grid.getColumns(); x++){
331
                grid.removeComponent(x, row);
332
            }
333
        }
334

    
335
        // set cursor at the beginning of the variable grid part
336
        grid.setCursorY(variableGridStartRow);
337
        grid.setCursorX(0);
338

    
339
        // place the fields which are required for the given referenceType in the variable grid part
340
        // and retain the original order which is recorded in the adaptiveFields
341
        try {
342
            Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(referenceType);
343

    
344
            datePublishedField.setVisible(fieldPropertyDefinition.containsKey("datePublished"));
345
            authorshipField.setVisible(fieldPropertyDefinition.containsKey("authorship"));
346
            String inRefCaption = fieldPropertyDefinition.get("inReference");
347
            inReferenceCombobox.setVisible(inRefCaption != null);
348
            inReferenceCombobox.setRequired(EnumSet.of(ReferenceType.Article, ReferenceType.BookSection, ReferenceType.Section, ReferenceType.InProceedings).contains(referenceType));
349
            if(inRefCaption != null){
350
                inReferenceCombobox.setCaption(inReferenceCaption(inRefCaption));
351
            }
352
            getField("title").setVisible(fieldPropertyDefinition.containsKey("title"));
353

    
354
            EnumSet<ReferenceType> hideNomTitle = EnumSet.of(ReferenceType.Article, ReferenceType.Section, ReferenceType.BookSection, ReferenceType.InProceedings);
355
            getField("abbrevTitle").setVisible(!hideNomTitle.contains(referenceType));
356
            institutionCombobox.setVisible(fieldPropertyDefinition.containsKey("institution"));
357
            schoolCombobox.setVisible(fieldPropertyDefinition.containsKey("school"));
358

    
359
            int componentCount = 0;
360
            for(String fieldName : adaptiveFields.keySet()){ // iterate over the LinkedHashMap to retain the original order of the fields
361
                if(fieldPropertyDefinition.containsKey(fieldName)){
362
                    Field<?> field = adaptiveFields.get(fieldName);
363
                    grid.addComponent(field);
364
                    componentCount++;
365
                    String propertyName = fieldPropertyDefinition.get(fieldName);
366
                    if(propertyName != fieldName){
367
                        field.setCaption(inReferenceCaption(propertyName));
368
                    }
369
                }
370
            }
371
            // add placeholders to fill the remaining cells in the row
372
            for(int pi = componentCount % 4; pi > 0; pi--){
373
                Label placeholder = new Label();
374
                placeholder.setWidth(COL_FIELD_WIDTH_STR);
375
                grid.addComponent(placeholder);
376
            }
377
        } catch (UnimplemetedCaseException e) {
378
            logger.error(e);
379
            // enable all fields
380
            setAllFieldsVisible(true);
381
            // fix inReference label
382
            getField("inReference").setCaption(propertyNameLabelMap.get("inReference"));
383
        }
384

    
385

    
386

    
387
        return null;
388
    }
389

    
390
    /**
391
     * @param inRefCaption
392
     * @return
393
     */
394
    public String inReferenceCaption(String inRefCaption) {
395
        String caption = propertyNameLabelMap.get(inRefCaption);
396

    
397
        return caption != null ? caption : inRefCaption;
398
    }
399

    
400
    /**
401
     * @param grid
402
     */
403
    protected void initAdaptiveFields() {
404
        GridLayout grid = (GridLayout)getFieldLayout();
405
        // initialize the map of adaptive fields
406
        if(adaptiveFields.isEmpty()){
407
            try{
408
                Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(null);
409
                Set<String> fieldNames = fieldPropertyDefinition.keySet();
410
                for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
411
                    for(int x=0; x < grid.getColumns(); x++){
412
                        Component c = grid.getComponent(x, row);
413
                        logger.trace("initAdaptiveFields() - y: " + row + " x: " + x + "  component:" + (c != null ? c.getClass().getSimpleName(): "NULL"));
414
                        if(c != null && c instanceof Field){
415
                            Field<?> field = (Field<?>)c;
416
                            PropertyIdPath propertyIdPath = boundPropertyIdPath(field);
417
                            logger.trace("initAdaptiveFields() - " + field.getCaption() + " -> " + propertyIdPath);
418
                            if(propertyIdPath != null && fieldNames.contains(propertyIdPath.toString())){
419
                                adaptiveFields.put(propertyIdPath.toString(), field);
420
                            }
421
                        }
422
                    }
423
                }
424
            } catch (UnimplemetedCaseException e) {
425
                throw new RuntimeException(e);
426
            }
427
        }
428
    }
429

    
430
    protected void setAllFieldsVisible(boolean visible){
431
        GridLayout grid = (GridLayout)getFieldLayout();
432
        for(Component c : grid){
433
            if(AbstractField.class.isAssignableFrom(c.getClass())){
434
                c.setVisible(visible);
435
            }
436
        }
437
    }
438

    
439

    
440
    @Override
441
    public void setAdvancedMode(boolean isAdvancedMode) {
442
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProberImpl(RolesAndPermissions.ROLE_CURATION));
443
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
444

    
445
        boolean canEditAllCaches = isAdmin || isCurator;
446
        super.setAdvancedMode(isAdvancedMode);
447
        if(!canEditAllCaches){
448
            advancedModeComponents.forEach(c -> c.setReadOnly(true));
449
            Arrays.asList(authorshipField.getCachFields()).forEach(c -> c.setReadOnly(false));
450
        }
451
    }
452

    
453

    
454
    /**
455
     * {@inheritDoc}
456
     */
457
    @Override
458
    public String getWindowCaption() {
459
        return "Reference editor";
460
    }
461

    
462
    /**
463
     * {@inheritDoc}
464
     */
465
    @Override
466
    protected String getDefaultComponentStyles() {
467
        return "tiny";
468
    }
469

    
470
    /**
471
     * {@inheritDoc}            // TODO Auto-generated method stub
472
     */
473
    @Override
474
    public void focusFirst() {
475
        titleField.focus();
476
    }
477

    
478
    /**
479
     * {@inheritDoc}
480
     */
481
    @Override
482
    public boolean isResizable() {
483
        return false;
484
    }
485

    
486
    @Override
487
    public NativeSelect getTypeSelect() {
488
        return typeSelect;
489
    }
490

    
491
    /**
492
     * {@inheritDoc}
493
     */
494
    @Override
495
    public ToOneRelatedEntityCombobox<Reference> getInReferenceCombobox() {
496
        return inReferenceCombobox;
497
    }
498

    
499
    /**
500
     * {@inheritDoc}
501
     */
502
    @Override
503
    public TeamOrPersonField getAuthorshipField() {
504
        return authorshipField;
505
    }
506

    
507
    @Override
508
    public FilterableAnnotationsField getAnnotationsField() {
509
        return annotationsListField;
510
    }
511

    
512
    public void withReferenceTypes(EnumSet<ReferenceType> types){
513
        this.referenceTypes = types;
514
        if(typeSelect != null){
515
            typeSelect.removeAllItems();
516
            typeSelect.addItems(referenceTypes);
517
        }
518
    }
519

    
520
    @Override
521
    public ToOneRelatedEntityCombobox<Institution> getInstitutionCombobox() {
522
        return institutionCombobox;
523
    }
524

    
525
    @Override
526
    public ToOneRelatedEntityCombobox<Institution> getSchoolCombobox() {
527
        return schoolCombobox;
528
    }
529

    
530

    
531
}
(2-2/4)