Project

General

Profile

Download (19.9 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.Label;
28
import com.vaadin.ui.NativeSelect;
29
import com.vaadin.ui.TextField;
30

    
31
import eu.etaxonomy.cdm.api.utility.RoleProberImpl;
32
import eu.etaxonomy.cdm.model.agent.Institution;
33
import eu.etaxonomy.cdm.model.common.AnnotationType;
34
import eu.etaxonomy.cdm.model.reference.Reference;
35
import eu.etaxonomy.cdm.model.reference.ReferencePropertyDefinitions;
36
import eu.etaxonomy.cdm.model.reference.ReferencePropertyDefinitions.UnimplemetedCaseException;
37
import eu.etaxonomy.cdm.model.reference.ReferenceType;
38
import eu.etaxonomy.cdm.service.UserHelperAccess;
39
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
40
import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
41
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
42
import eu.etaxonomy.cdm.vaadin.component.common.VerbatimTimePeriodField;
43
import eu.etaxonomy.cdm.vaadin.data.validator.InReferenceTypeValidator;
44
import eu.etaxonomy.cdm.vaadin.data.validator.TimePeriodCompletenesValidator;
45
import eu.etaxonomy.cdm.vaadin.event.InstitutionEditorAction;
46
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
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;
58

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

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

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

    
72
    private TextField titleField;
73

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

    
76
    private final static int GRID_ROWS = 14;
77

    
78
    private final static int COL_FIELD_WIDTH_PX = 160;
79

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

    
82
    private NativeSelect typeSelect;
83

    
84
    private ToOneRelatedEntityCombobox<Reference> inReferenceCombobox;
85

    
86
    private TeamOrPersonField authorshipField;
87

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

    
91
    private FilterableAnnotationsField annotationsListField;
92

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

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

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

    
99
    private int variableGridStartRow;
100

    
101
    private int variableGridLastRow;
102

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

    
108
    private VerbatimTimePeriodField datePublishedField;
109

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

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

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

    
132

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

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

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

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

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

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

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

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

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

    
256
        variableGridStartRow = row;
257

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

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

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

    
283

    
284
        variableGridLastRow = row;
285

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

    
298

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

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

    
307
    }
308

    
309

    
310

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

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

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

    
325
        initAdaptiveFields();
326

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

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

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

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

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

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

    
384

    
385

    
386
        return null;
387
    }
388

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

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

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

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

    
438

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

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

    
452

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

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

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

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

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

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

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

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

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

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

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

    
529

    
530
}
(2-2/4)