Project

General

Profile

Download (18.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.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.event.InstitutionEditorAction;
44
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
45
import eu.etaxonomy.cdm.vaadin.permission.RolesAndPermissions;
46
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
47
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
48
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
49
import eu.etaxonomy.cdm.vaadin.util.converter.DoiConverter;
50
import eu.etaxonomy.cdm.vaadin.util.converter.UriConverter;
51
import eu.etaxonomy.vaadin.component.SwitchableTextField;
52
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
53
import eu.etaxonomy.vaadin.event.EditorActionType;
54
import eu.etaxonomy.vaadin.mvp.AbstractCdmPopupEditor;
55
import eu.etaxonomy.vaadin.util.PropertyIdPath;
56

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

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

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

    
70
    private TextField titleField;
71

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

    
74
    private final static int GRID_ROWS = 14;
75

    
76
    private NativeSelect typeSelect;
77

    
78
    private ToOneRelatedEntityCombobox<Reference> inReferenceCombobox;
79

    
80
    private TeamOrPersonField authorshipField;
81

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

    
85
    private FilterableAnnotationsField annotationsListField;
86

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

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

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

    
93
    private int variableGridStartRow;
94

    
95
    private int variableGridLastRow;
96

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

    
102
    private VerbatimTimePeriodField datePublishedField;
103

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

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

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

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

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

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

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

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

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

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

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

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

    
248
        variableGridStartRow = row;
249

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

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

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

    
275

    
276
        variableGridLastRow = row;
277

    
278
        row++;
279
        annotationsListField = new FilterableAnnotationsField("Editorial notes");
280
        annotationsListField.setWidth(100, Unit.PERCENTAGE);
281
        annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
282
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
283

    
284

    
285
//        titleField.setRequired(true);
286
//        publisherField.setRequired(true);
287

    
288
        setAdvancedModeEnabled(true);
289
        registerAdvancedModeComponents(titleCacheField, abbrevTitleCacheField);
290
        registerAdvancedModeComponents(authorshipField.getCachFields());
291
        setAdvancedMode(false);
292

    
293
    }
294

    
295

    
296

    
297
    @Override
298
    protected void afterItemDataSourceSet() {
299
        super.afterItemDataSourceSet();
300
        inReferenceCombobox.getSelect().addValidator(new InReferenceTypeValidator(typeSelect));
301
    }
302

    
303
    /**
304
     * @param value
305
     * @return
306
     */
307
    private Object updateFieldVisibility(ReferenceType referenceType) {
308

    
309
        GridLayout grid = (GridLayout)getFieldLayout();
310

    
311
        initAdaptiveFields();
312

    
313
        // clear the variable grid part
314
        for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
315
            for(int x=0; x < grid.getColumns(); x++){
316
                grid.removeComponent(x, row);
317
            }
318
        }
319

    
320
        // set cursor at the beginning of the variable grid part
321
        grid.setCursorY(variableGridStartRow);
322
        grid.setCursorX(0);
323

    
324
        // place the fields which are required for the given referenceType in the variable grid part while
325
        // and retain the original order which is recorded in the adaptiveFields
326
        try {
327
            Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(referenceType);
328

    
329
            datePublishedField.setVisible(fieldPropertyDefinition.containsKey("datePublished"));
330
            authorshipField.setVisible(fieldPropertyDefinition.containsKey("authorship"));
331
            String inRefCaption = fieldPropertyDefinition.get("inReference");
332
            inReferenceCombobox.setVisible(inRefCaption != null);
333
            inReferenceCombobox.setRequired(referenceType.isSection());
334
            if(inRefCaption != null){
335
                inReferenceCombobox.setCaption(inReferenceCaption(inRefCaption));
336
            }
337
            getField("title").setVisible(fieldPropertyDefinition.containsKey("title"));
338

    
339
            EnumSet<ReferenceType> hideNomTitle = EnumSet.of(ReferenceType.Article, ReferenceType.Section, ReferenceType.BookSection, ReferenceType.InProceedings);
340
            getField("abbrevTitle").setVisible(!hideNomTitle.contains(referenceType));
341
            institutionCombobox.setVisible(fieldPropertyDefinition.containsKey("institution"));
342
            schoolCombobox.setVisible(fieldPropertyDefinition.containsKey("school"));
343

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

    
362

    
363

    
364
        return null;
365
    }
366

    
367
    /**
368
     * @param inRefCaption
369
     * @return
370
     */
371
    public String inReferenceCaption(String inRefCaption) {
372
        String caption = propertyNameLabelMap.get(inRefCaption);
373

    
374
        return caption != null ? caption : inRefCaption;
375
    }
376

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

    
407
    protected void setAllFieldsVisible(boolean visible){
408
        GridLayout grid = (GridLayout)getFieldLayout();
409
        for(Component c : grid){
410
            if(AbstractField.class.isAssignableFrom(c.getClass())){
411
                c.setVisible(visible);
412
            }
413
        }
414
    }
415

    
416

    
417
    @Override
418
    public void setAdvancedMode(boolean isAdvancedMode) {
419
        boolean isCurator = UserHelperAccess.userHelper().userIs(new RoleProber(RolesAndPermissions.ROLE_CURATION));
420
        boolean isAdmin = UserHelperAccess.userHelper().userIsAdmin();
421

    
422
        boolean canEditAllCaches = isAdmin || isCurator;
423
        super.setAdvancedMode(isAdvancedMode);
424
        if(!canEditAllCaches){
425
            advancedModeComponents.forEach(c -> c.setReadOnly(true));
426
            Arrays.asList(authorshipField.getCachFields()).forEach(c -> c.setReadOnly(false));
427
        }
428
    }
429

    
430

    
431
    /**
432
     * {@inheritDoc}
433
     */
434
    @Override
435
    public String getWindowCaption() {
436
        return "Reference editor";
437
    }
438

    
439
    /**
440
     * {@inheritDoc}
441
     */
442
    @Override
443
    protected String getDefaultComponentStyles() {
444
        return "tiny";
445
    }
446

    
447
    /**
448
     * {@inheritDoc}            // TODO Auto-generated method stub
449
     */
450
    @Override
451
    public void focusFirst() {
452
        titleField.focus();
453
    }
454

    
455
    /**
456
     * {@inheritDoc}
457
     */
458
    @Override
459
    public boolean isResizable() {
460
        return false;
461
    }
462

    
463
    @Override
464
    public NativeSelect getTypeSelect() {
465
        return typeSelect;
466
    }
467

    
468
    /**
469
     * {@inheritDoc}
470
     */
471
    @Override
472
    public ToOneRelatedEntityCombobox<Reference> getInReferenceCombobox() {
473
        return inReferenceCombobox;
474
    }
475

    
476
    /**
477
     * {@inheritDoc}
478
     */
479
    @Override
480
    public TeamOrPersonField getAuthorshipField() {
481
        return authorshipField;
482
    }
483

    
484
    @Override
485
    public FilterableAnnotationsField getAnnotationsField() {
486
        return annotationsListField;
487
    }
488

    
489
    public void withReferenceTypes(EnumSet<ReferenceType> types){
490
        this.referenceTypes = types;
491
        if(typeSelect != null){
492
            typeSelect.removeAllItems();
493
            typeSelect.addItems(referenceTypes);
494
        }
495
    }
496

    
497
    @Override
498
    public ToOneRelatedEntityCombobox<Institution> getInstitutionCombobox() {
499
        return institutionCombobox;
500
    }
501

    
502
    @Override
503
    public ToOneRelatedEntityCombobox<Institution> getSchoolCombobox() {
504
        return schoolCombobox;
505
    }
506

    
507

    
508
}
(2-2/3)