Project

General

Profile

Download (17.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.Collection;
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
import org.springframework.security.core.GrantedAuthority;
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.ListSelect;
29
import com.vaadin.ui.TextField;
30

    
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.vaadin.component.TextFieldNFix;
38
import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
39
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
40
import eu.etaxonomy.cdm.vaadin.component.common.VerbatimTimePeriodField;
41
import eu.etaxonomy.cdm.vaadin.event.InstitutionEditorAction;
42
import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
43
import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
44
import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
45
import eu.etaxonomy.cdm.vaadin.util.CdmTitleCacheCaptionGenerator;
46
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
47
import eu.etaxonomy.cdm.vaadin.util.converter.DoiConverter;
48
import eu.etaxonomy.cdm.vaadin.util.converter.UriConverter;
49
import eu.etaxonomy.vaadin.component.SwitchableTextField;
50
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
51
import eu.etaxonomy.vaadin.event.EditorActionType;
52
import eu.etaxonomy.vaadin.mvp.AbstractCdmPopupEditor;
53
import eu.etaxonomy.vaadin.util.PropertyIdPath;
54

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

    
64
    private static final long serialVersionUID = -4347633563800758815L;
65

    
66
    private static final Logger logger = Logger.getLogger(ReferencePopupEditor.class);
67

    
68
    private TextField titleField;
69

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

    
72
    private final static int GRID_ROWS = 14;
73

    
74
    private ListSelect typeSelect;
75

    
76
    private ToOneRelatedEntityCombobox<Reference> inReferenceCombobox;
77

    
78
    private TeamOrPersonField authorshipField;
79

    
80
    private ToOneRelatedEntityCombobox<Institution> institutionCombobox;
81
    private ToOneRelatedEntityCombobox<Institution> schoolCombobox;
82

    
83
    private FilterableAnnotationsField annotationsListField;
84

    
85
    private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
86

    
87
    private EnumSet<ReferenceType> referenceTypes = EnumSet.allOf(ReferenceType.class);
88

    
89
    private static Map<String,String> propertyNameLabelMap = new HashMap<>();
90

    
91
    private int variableGridStartRow;
92

    
93
    private int variableGridLastRow;
94

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

    
100
    private VerbatimTimePeriodField datePublishedField;
101

    
102
    static {
103
        propertyNameLabelMap.put("inReference", "In reference");
104
        propertyNameLabelMap.put("inJournal", "In journal");
105
        propertyNameLabelMap.put("inSeries", "In series");
106
        propertyNameLabelMap.put("inBook", "In book");
107
    }
108

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

    
117
    @Override
118
    protected void initContent() {
119
        GridLayout grid = (GridLayout)getFieldLayout();
120
        grid.setSpacing(true);
121
        grid.setMargin(true);
122

    
123
        /*
124
        "type",
125
        "uri",
126
        "abbrevTitleCache",
127
        "protectedAbbrevTitleCache",
128
        "nomenclaturallyRelevant",
129
        "authorship",
130
        "referenceAbstract",
131
        "title",
132
        "abbrevTitle",
133
        "editor",
134
        "volume",
135
        "pages",
136
        "edition",
137
        "isbn",
138
        "issn",
139
        "doi",
140
        "seriesPart",
141
        "datePublished",
142
        "publisher",
143
        "placePublished",
144
        "institution",
145
        "school",
146
        "organization",
147
        "inReference"
148
         */
149
        int row = 0;
150
        datePublishedField = new VerbatimTimePeriodField("Date published");
151
        addField(datePublishedField, "datePublished", 0, row, 1, row);
152
        typeSelect = new ListSelect("Reference type");
153
        typeSelect.addItems(referenceTypes);
154
        typeSelect.setNullSelectionAllowed(false);
155
        typeSelect.setRows(1);
156
        typeSelect.addValueChangeListener(e -> updateFieldVisibility((ReferenceType)e.getProperty().getValue()));
157
        addField(typeSelect, "type", GRID_COLS - 1, row);
158
        grid.setComponentAlignment(typeSelect, Alignment.TOP_RIGHT);
159
        row++;
160

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

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

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

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

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

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

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

    
245
        variableGridStartRow = row;
246

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

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

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

    
272

    
273
        variableGridLastRow = row;
274

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

    
281

    
282
//        titleField.setRequired(true);
283
//        publisherField.setRequired(true);
284

    
285
        setAdvancedModeEnabled(true);
286
        registerAdvancedModeComponents(titleCacheField, abbrevTitleCacheField);
287
        registerAdvancedModeComponents(authorshipField.getCachFields());
288
        setAdvancedMode(false);
289

    
290
    }
291

    
292
    /**
293
     * @param value
294
     * @return
295
     */
296
    private Object updateFieldVisibility(ReferenceType referenceType) {
297

    
298
        GridLayout grid = (GridLayout)getFieldLayout();
299

    
300
        initAdaptiveFields();
301

    
302
        // clear the variable grid part
303
        for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
304
            for(int x=0; x < grid.getColumns(); x++){
305
                grid.removeComponent(x, row);
306
            }
307
        }
308

    
309
        // set cursor at the beginning of the variable grid part
310
        grid.setCursorY(variableGridStartRow);
311
        grid.setCursorX(0);
312

    
313
        // place the fields which are required for the given referenceType in the variable grid part while
314
        // and retain the original order which is recorded in the adaptiveFields
315
        try {
316
            Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(referenceType);
317

    
318
            datePublishedField.setVisible(fieldPropertyDefinition.containsKey("datePublished"));
319
            authorshipField.setVisible(fieldPropertyDefinition.containsKey("authorship"));
320
            String inRefCaption = fieldPropertyDefinition.get("inReference");
321
            inReferenceCombobox.setVisible(inRefCaption != null);
322
            if(inRefCaption != null){
323
                inReferenceCombobox.setCaption(propertyNameLabelMap.get(inRefCaption));
324
            }
325
            getField("title").setVisible(fieldPropertyDefinition.containsKey("title"));
326

    
327
            EnumSet<ReferenceType> hideNomTitle = EnumSet.of(ReferenceType.Article, ReferenceType.Section, ReferenceType.BookSection, ReferenceType.InProceedings);
328
            getField("abbrevTitle").setVisible(!hideNomTitle.contains(referenceType));
329
            institutionCombobox.setVisible(fieldPropertyDefinition.containsKey("institution"));
330
            schoolCombobox.setVisible(fieldPropertyDefinition.containsKey("school"));
331

    
332
            for(String fieldName : adaptiveFields.keySet()){ // iterate over the LinkedHashMap to retain the original order of the fields
333
                if(fieldPropertyDefinition.containsKey(fieldName)){
334
                    Field<?> field = adaptiveFields.get(fieldName);
335
                    grid.addComponent(field);
336
                    String propertyName = fieldPropertyDefinition.get(fieldName);
337
                    if(propertyName != fieldName){
338
                        field.setCaption(propertyNameLabelMap.get(propertyName));
339
                    }
340
                }
341
            }
342
        } catch (UnimplemetedCaseException e) {
343
            logger.error(e);
344
            // enable all fields
345
            setAllFieldsVisible(true);
346
            // fix inReference label
347
            getField("inReference").setCaption(propertyNameLabelMap.get("inReference"));
348
        }
349

    
350

    
351

    
352
        return null;
353
    }
354

    
355
    /**
356
     * @param grid
357
     */
358
    protected void initAdaptiveFields() {
359
        GridLayout grid = (GridLayout)getFieldLayout();
360
        // initialize the map of adaptive fields
361
        if(adaptiveFields.isEmpty()){
362
            try{
363
                Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(null);
364
                Set<String> fieldNames = fieldPropertyDefinition.keySet();
365
                for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
366
                    for(int x=0; x < grid.getColumns(); x++){
367
                        Component c = grid.getComponent(x, row);
368
                        logger.trace("initAdaptiveFields() - y: " + row + " x: " + x + "  component:" + (c != null ? c.getClass().getSimpleName(): "NULL"));
369
                        if(c != null && c instanceof Field){
370
                            Field<?> field = (Field<?>)c;
371
                            PropertyIdPath propertyIdPath = boundPropertyIdPath(field);
372
                            logger.trace("initAdaptiveFields() - " + field.getCaption() + " -> " + propertyIdPath);
373
                            if(propertyIdPath != null && fieldNames.contains(propertyIdPath.toString())){
374
                                adaptiveFields.put(propertyIdPath.toString(), field);
375
                            }
376
                        }
377
                    }
378
                }
379
            } catch (UnimplemetedCaseException e) {
380
                throw new RuntimeException(e);
381
            }
382
        }
383
    }
384

    
385
    protected void setAllFieldsVisible(boolean visible){
386
        GridLayout grid = (GridLayout)getFieldLayout();
387
        for(Component c : grid){
388
            if(AbstractField.class.isAssignableFrom(c.getClass())){
389
                c.setVisible(visible);
390
            }
391
        }
392
    }
393

    
394
    /**
395
     * {@inheritDoc}
396
     */
397
    @Override
398
    public String getWindowCaption() {
399
        return "Reference editor";
400
    }
401

    
402
    /**
403
     * {@inheritDoc}
404
     */
405
    @Override
406
    protected String getDefaultComponentStyles() {
407
        return "tiny";
408
    }
409

    
410
    /**
411
     * {@inheritDoc}            // TODO Auto-generated method stub
412
     */
413
    @Override
414
    public void focusFirst() {
415
        titleField.focus();
416
    }
417

    
418
    /**
419
     * {@inheritDoc}
420
     */
421
    @Override
422
    public boolean isResizable() {
423
        return false;
424
    }
425

    
426
    /**
427
     * {@inheritDoc}
428
     */
429
    @Override
430
    public boolean allowAnonymousAccess() {
431
        return false;
432
    }
433

    
434
    /**
435
     * {@inheritDoc}
436
     */
437
    @Override
438
    public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
439
        return null;
440
    }
441

    
442
    @Override
443
    public ListSelect getTypeSelect() {
444
        return typeSelect;
445
    }
446

    
447
    /**
448
     * {@inheritDoc}
449
     */
450
    @Override
451
    public ToOneRelatedEntityCombobox<Reference> getInReferenceCombobox() {
452
        return inReferenceCombobox;
453
    }
454

    
455
    /**
456
     * {@inheritDoc}
457
     */
458
    @Override
459
    public TeamOrPersonField getAuthorshipField() {
460
        return authorshipField;
461
    }
462

    
463
    @Override
464
    public FilterableAnnotationsField getAnnotationsField() {
465
        return annotationsListField;
466
    }
467

    
468
    public void withReferenceTypes(EnumSet<ReferenceType> types){
469
        this.referenceTypes = types;
470
        if(typeSelect != null){
471
            typeSelect.removeAllItems();
472
            typeSelect.addItems(referenceTypes);
473
        }
474
    }
475

    
476
    @Override
477
    public ToOneRelatedEntityCombobox<Institution> getInstitutionCombobox() {
478
        return institutionCombobox;
479
    }
480

    
481
    @Override
482
    public ToOneRelatedEntityCombobox<Institution> getSchoolCombobox() {
483
        return schoolCombobox;
484
    }
485

    
486

    
487
}
(2-2/3)