Project

General

Profile

Download (19 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 fits 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
        annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
284
        addField(annotationsListField, "annotations", 0, row, GRID_COLS-1, row);
285

    
286

    
287
//        titleField.setRequired(true);
288
//        publisherField.setRequired(true);
289

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

    
295
    }
296

    
297

    
298

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

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

    
311
        GridLayout grid = (GridLayout)getFieldLayout();
312

    
313
        initAdaptiveFields();
314

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

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

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

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

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

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

    
364

    
365

    
366
        return null;
367
    }
368

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

    
376
        return caption != null ? caption : inRefCaption;
377
    }
378

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

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

    
418

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

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

    
432

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

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

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

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

    
465
    @Override
466
    public NativeSelect getTypeSelect() {
467
        return typeSelect;
468
    }
469

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

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

    
486
    @Override
487
    public FilterableAnnotationsField getAnnotationsField() {
488
        return annotationsListField;
489
    }
490

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

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

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

    
509

    
510
}
(2-2/4)