Project

General

Profile

Download (19.4 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.log4j.Logger;
19
import org.springframework.context.annotation.Scope;
20

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

    
30
import eu.etaxonomy.cdm.api.utility.RoleProber;
31
import eu.etaxonomy.cdm.model.agent.Institution;
32
import eu.etaxonomy.cdm.model.common.AnnotationType;
33
import eu.etaxonomy.cdm.model.reference.Reference;
34
import eu.etaxonomy.cdm.model.reference.ReferencePropertyDefinitions;
35
import eu.etaxonomy.cdm.model.reference.ReferencePropertyDefinitions.UnimplemetedCaseException;
36
import eu.etaxonomy.cdm.model.reference.ReferenceType;
37
import eu.etaxonomy.cdm.service.UserHelperAccess;
38
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
39
import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
40
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
41
import eu.etaxonomy.cdm.vaadin.component.common.VerbatimTimePeriodField;
42
import eu.etaxonomy.cdm.vaadin.data.validator.InReferenceTypeValidator;
43
import eu.etaxonomy.cdm.vaadin.data.validator.TimePeriodCompletenesValidator;
44
import eu.etaxonomy.cdm.vaadin.event.InstitutionEditorAction;
45
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
46
import eu.etaxonomy.cdm.vaadin.permission.RolesAndPermissions;
47
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
48
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
49
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
50
import eu.etaxonomy.cdm.vaadin.util.converter.DoiConverter;
51
import eu.etaxonomy.cdm.vaadin.util.converter.UriConverter;
52
import eu.etaxonomy.vaadin.component.SwitchableTextField;
53
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
54
import eu.etaxonomy.vaadin.event.EditorActionType;
55
import eu.etaxonomy.vaadin.mvp.AbstractCdmPopupEditor;
56
import eu.etaxonomy.vaadin.util.PropertyIdPath;
57

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

    
67
    private static final long serialVersionUID = -4347633563800758815L;
68

    
69
    private static final Logger logger = Logger.getLogger(ReferencePopupEditor.class);
70

    
71
    private TextField titleField;
72

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

    
75
    private final static int GRID_ROWS = 14;
76

    
77
    private NativeSelect typeSelect;
78

    
79
    private ToOneRelatedEntityCombobox<Reference> inReferenceCombobox;
80

    
81
    private TeamOrPersonField authorshipField;
82

    
83
    private ToOneRelatedEntityCombobox<Institution> institutionCombobox;
84
    private ToOneRelatedEntityCombobox<Institution> schoolCombobox;
85

    
86
    private FilterableAnnotationsField annotationsListField;
87

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

    
90
    private EnumSet<ReferenceType> referenceTypes = EnumSet.allOf(ReferenceType.class);
91

    
92
    private static Map<String,String> propertyNameLabelMap = new HashMap<>();
93

    
94
    private int variableGridStartRow;
95

    
96
    private int variableGridLastRow;
97

    
98
    /**
99
     * Used to record the fields from the variable grid part in their original order.
100
     */
101
    private LinkedHashMap<String, Field<?>> adaptiveFields = new LinkedHashMap<>();
102

    
103
    private VerbatimTimePeriodField datePublishedField;
104

    
105
    static {
106
        propertyNameLabelMap.put("inReference", "In reference");
107
        propertyNameLabelMap.put("inProceedings", "In proceedings");
108
        propertyNameLabelMap.put("inJournal", "In journal");
109
        propertyNameLabelMap.put("inSeries", "In series");
110
        propertyNameLabelMap.put("inBook", "In book");
111
    }
112

    
113
    /**
114
     * @param layout
115
     * @param dtoType
116
     */
117
    public ReferencePopupEditor() {
118
        super(new GridLayout(GRID_COLS, GRID_ROWS), Reference.class);
119
    }
120

    
121
    @Override
122
    protected void initContent() {
123
        GridLayout grid = (GridLayout)getFieldLayout();
124
        grid.setSpacing(true);
125
        grid.setMargin(true);
126

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

    
161
        typeSelect.addValueChangeListener(e -> updateFieldVisibility((ReferenceType)e.getProperty().getValue()));
162
        addField(typeSelect, "type", GRID_COLS - 1, row);
163
        grid.setComponentAlignment(typeSelect, Alignment.TOP_RIGHT);
164
        row++;
165

    
166
        SwitchableTextField titleCacheField = addSwitchableTextField("Reference cache", "titleCache", "protectedTitleCache", 0, row, GRID_COLS-1, row);
167
        titleCacheField.setWidth(100, Unit.PERCENTAGE);
168
        row++;
169

    
170
        SwitchableTextField abbrevTitleCacheField = addSwitchableTextField("Abbrev. cache", "abbrevTitleCache", "protectedAbbrevTitleCache", 0, row, GRID_COLS-1, row);
171
        abbrevTitleCacheField.setWidth(100, Unit.PERCENTAGE);
172
        row++;
173

    
174
        titleField = addTextField("Title", "title", 0, row, GRID_COLS-1, row);
175
        titleField.setWidth(100, Unit.PERCENTAGE);
176
        row++;
177
        addTextField("Nomenclatural title", "abbrevTitle", 0, row, GRID_COLS-1, row).setWidth(100, Unit.PERCENTAGE);
178
        row++;
179

    
180
        authorshipField = new TeamOrPersonField("Author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.BIBLIOGRAPHIC_TITLE);
181
        authorshipField.setWidth(100,  Unit.PERCENTAGE);
182
        addField(authorshipField, "authorship", 0, row, GRID_COLS -1, row);
183
        row++;
184

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

    
204
        institutionCombobox = new ToOneRelatedEntityCombobox<Institution>("Institution", Institution.class);
205
        institutionCombobox.getSelect().setCaptionGenerator(
206
                new CdmTitleCacheCaptionGenerator<Institution>()
207
                );
208
        institutionCombobox.setWidth(100, Unit.PERCENTAGE);
209
        institutionCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(this,
210
                new InstitutionEditorAction(EditorActionType.ADD, e.getButton(), institutionCombobox, this)
211
                ));
212
        institutionCombobox.addClickListenerEditEntity(e -> {
213
            if(institutionCombobox.getValue() != null){
214
                getViewEventBus().publish(this,
215
                    new InstitutionEditorAction(
216
                            EditorActionType.EDIT,
217
                            institutionCombobox.getValue().getUuid(),
218
                            e.getButton(),
219
                            institutionCombobox,
220
                            this)
221
                );
222
            }
223
         });
224

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

    
250
        variableGridStartRow = row;
251

    
252
        addTextField("Organization", "organization", 0, row).setWidth(100, Unit.PERCENTAGE);
253
        row++;
254
        addTextField("Series", "seriesPart", 0, row).setWidth(100, Unit.PERCENTAGE);
255
        addTextField("Volume", "volume", 1, row).setWidth(100, Unit.PERCENTAGE);
256
        addTextField("Pages", "pages", 2, row).setWidth(100, Unit.PERCENTAGE);
257
        addTextField("Edition", "edition", 3, row).setWidth(100, Unit.PERCENTAGE);
258
        row++;
259

    
260
        addTextField("Place published", "placePublished", 0, row, 0, row).setWidth(100, Unit.PERCENTAGE);
261
        TextField publisherField = addTextField("Publisher", "publisher", 1, row, 1, row);
262
        publisherField.setWidth(100, Unit.PERCENTAGE);
263
        addTextField("Editor", "editor", 2, row).setWidth(100, Unit.PERCENTAGE);
264
        row++;
265

    
266
        addTextField("ISSN", "issn", 0, row).setWidth(100, Unit.PERCENTAGE);
267
        addTextField("ISBN", "isbn", 1, row).setWidth(100, Unit.PERCENTAGE);
268
        TextFieldNFix doiField = new TextFieldNFix("DOI");
269
        doiField.setConverter(new DoiConverter());
270
        doiField.setWidth(100, Unit.PERCENTAGE);
271
        addField(doiField, "doi", 2, row);
272
        TextFieldNFix uriField = new TextFieldNFix("Uri");
273
        uriField.setConverter(new UriConverter());
274
        uriField.setWidth(100, Unit.PERCENTAGE);
275
        addField(uriField, "uri", 3, row);
276

    
277

    
278
        variableGridLastRow = row;
279

    
280
        row++;
281
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
282
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
283
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProber(RolesAndPermissions.ROLE_CURATION));
284
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
285
        if(isCurator || isAdmin){
286
            annotationsListField.withNewButton(true);
287
        } else {
288
            annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
289
        }
290
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
291

    
292

    
293
//        titleField.setRequired(true);
294
//        publisherField.setRequired(true);
295

    
296
        setAdvancedModeEnabled(true);
297
        registerAdvancedModeComponents(titleCacheField, abbrevTitleCacheField);
298
        registerAdvancedModeComponents(authorshipField.getCachFields());
299
        setAdvancedMode(false);
300

    
301
    }
302

    
303

    
304

    
305
    @Override
306
    protected void afterItemDataSourceSet() {
307
        super.afterItemDataSourceSet();
308
        inReferenceCombobox.getSelect().addValidator(new InReferenceTypeValidator(typeSelect));
309
    }
310

    
311
    /**
312
     * @param value
313
     * @return
314
     */
315
    private Object updateFieldVisibility(ReferenceType referenceType) {
316

    
317
        GridLayout grid = (GridLayout)getFieldLayout();
318

    
319
        initAdaptiveFields();
320

    
321
        // clear the variable grid part
322
        for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
323
            for(int x=0; x < grid.getColumns(); x++){
324
                grid.removeComponent(x, row);
325
            }
326
        }
327

    
328
        // set cursor at the beginning of the variable grid part
329
        grid.setCursorY(variableGridStartRow);
330
        grid.setCursorX(0);
331

    
332
        // place the fields which are required for the given referenceType in the variable grid part while
333
        // and retain the original order which is recorded in the adaptiveFields
334
        try {
335
            Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(referenceType);
336

    
337
            datePublishedField.setVisible(fieldPropertyDefinition.containsKey("datePublished"));
338
            authorshipField.setVisible(fieldPropertyDefinition.containsKey("authorship"));
339
            String inRefCaption = fieldPropertyDefinition.get("inReference");
340
            inReferenceCombobox.setVisible(inRefCaption != null);
341
            inReferenceCombobox.setRequired(EnumSet.of(ReferenceType.Article, ReferenceType.BookSection, ReferenceType.Section, ReferenceType.InProceedings).contains(referenceType));
342
            if(inRefCaption != null){
343
                inReferenceCombobox.setCaption(inReferenceCaption(inRefCaption));
344
            }
345
            getField("title").setVisible(fieldPropertyDefinition.containsKey("title"));
346

    
347
            EnumSet<ReferenceType> hideNomTitle = EnumSet.of(ReferenceType.Article, ReferenceType.Section, ReferenceType.BookSection, ReferenceType.InProceedings);
348
            getField("abbrevTitle").setVisible(!hideNomTitle.contains(referenceType));
349
            institutionCombobox.setVisible(fieldPropertyDefinition.containsKey("institution"));
350
            schoolCombobox.setVisible(fieldPropertyDefinition.containsKey("school"));
351

    
352
            for(String fieldName : adaptiveFields.keySet()){ // iterate over the LinkedHashMap to retain the original order of the fields
353
                if(fieldPropertyDefinition.containsKey(fieldName)){
354
                    Field<?> field = adaptiveFields.get(fieldName);
355
                    grid.addComponent(field);
356
                    String propertyName = fieldPropertyDefinition.get(fieldName);
357
                    if(propertyName != fieldName){
358
                        field.setCaption(inReferenceCaption(propertyName));
359
                    }
360
                }
361
            }
362
        } catch (UnimplemetedCaseException e) {
363
            logger.error(e);
364
            // enable all fields
365
            setAllFieldsVisible(true);
366
            // fix inReference label
367
            getField("inReference").setCaption(propertyNameLabelMap.get("inReference"));
368
        }
369

    
370

    
371

    
372
        return null;
373
    }
374

    
375
    /**
376
     * @param inRefCaption
377
     * @return
378
     */
379
    public String inReferenceCaption(String inRefCaption) {
380
        String caption = propertyNameLabelMap.get(inRefCaption);
381

    
382
        return caption != null ? caption : inRefCaption;
383
    }
384

    
385
    /**
386
     * @param grid
387
     */
388
    protected void initAdaptiveFields() {
389
        GridLayout grid = (GridLayout)getFieldLayout();
390
        // initialize the map of adaptive fields
391
        if(adaptiveFields.isEmpty()){
392
            try{
393
                Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(null);
394
                Set<String> fieldNames = fieldPropertyDefinition.keySet();
395
                for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
396
                    for(int x=0; x < grid.getColumns(); x++){
397
                        Component c = grid.getComponent(x, row);
398
                        logger.trace("initAdaptiveFields() - y: " + row + " x: " + x + "  component:" + (c != null ? c.getClass().getSimpleName(): "NULL"));
399
                        if(c != null && c instanceof Field){
400
                            Field<?> field = (Field<?>)c;
401
                            PropertyIdPath propertyIdPath = boundPropertyIdPath(field);
402
                            logger.trace("initAdaptiveFields() - " + field.getCaption() + " -> " + propertyIdPath);
403
                            if(propertyIdPath != null && fieldNames.contains(propertyIdPath.toString())){
404
                                adaptiveFields.put(propertyIdPath.toString(), field);
405
                            }
406
                        }
407
                    }
408
                }
409
            } catch (UnimplemetedCaseException e) {
410
                throw new RuntimeException(e);
411
            }
412
        }
413
    }
414

    
415
    protected void setAllFieldsVisible(boolean visible){
416
        GridLayout grid = (GridLayout)getFieldLayout();
417
        for(Component c : grid){
418
            if(AbstractField.class.isAssignableFrom(c.getClass())){
419
                c.setVisible(visible);
420
            }
421
        }
422
    }
423

    
424

    
425
    @Override
426
    public void setAdvancedMode(boolean isAdvancedMode) {
427
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProber(RolesAndPermissions.ROLE_CURATION));
428
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
429

    
430
        boolean canEditAllCaches = isAdmin || isCurator;
431
        super.setAdvancedMode(isAdvancedMode);
432
        if(!canEditAllCaches){
433
            advancedModeComponents.forEach(c -> c.setReadOnly(true));
434
            Arrays.asList(authorshipField.getCachFields()).forEach(c -> c.setReadOnly(false));
435
        }
436
    }
437

    
438

    
439
    /**
440
     * {@inheritDoc}
441
     */
442
    @Override
443
    public String getWindowCaption() {
444
        return "Reference editor";
445
    }
446

    
447
    /**
448
     * {@inheritDoc}
449
     */
450
    @Override
451
    protected String getDefaultComponentStyles() {
452
        return "tiny";
453
    }
454

    
455
    /**
456
     * {@inheritDoc}            // TODO Auto-generated method stub
457
     */
458
    @Override
459
    public void focusFirst() {
460
        titleField.focus();
461
    }
462

    
463
    /**
464
     * {@inheritDoc}
465
     */
466
    @Override
467
    public boolean isResizable() {
468
        return false;
469
    }
470

    
471
    @Override
472
    public NativeSelect getTypeSelect() {
473
        return typeSelect;
474
    }
475

    
476
    /**
477
     * {@inheritDoc}
478
     */
479
    @Override
480
    public ToOneRelatedEntityCombobox<Reference> getInReferenceCombobox() {
481
        return inReferenceCombobox;
482
    }
483

    
484
    /**
485
     * {@inheritDoc}
486
     */
487
    @Override
488
    public TeamOrPersonField getAuthorshipField() {
489
        return authorshipField;
490
    }
491

    
492
    @Override
493
    public FilterableAnnotationsField getAnnotationsField() {
494
        return annotationsListField;
495
    }
496

    
497
    public void withReferenceTypes(EnumSet<ReferenceType> types){
498
        this.referenceTypes = types;
499
        if(typeSelect != null){
500
            typeSelect.removeAllItems();
501
            typeSelect.addItems(referenceTypes);
502
        }
503
    }
504

    
505
    @Override
506
    public ToOneRelatedEntityCombobox<Institution> getInstitutionCombobox() {
507
        return institutionCombobox;
508
    }
509

    
510
    @Override
511
    public ToOneRelatedEntityCombobox<Institution> getSchoolCombobox() {
512
        return schoolCombobox;
513
    }
514

    
515

    
516
}
(2-2/4)