Project

General

Profile

Download (13.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.component.common;
10

    
11
import java.util.EnumSet;
12
import java.util.List;
13
import java.util.Optional;
14
import java.util.regex.Pattern;
15

    
16
import org.vaadin.teemu.switchui.Switch;
17
import org.vaadin.viritin.fields.LazyComboBox;
18

    
19
import com.vaadin.data.Validator.InvalidValueException;
20
import com.vaadin.data.fieldgroup.BeanFieldGroup;
21
import com.vaadin.data.fieldgroup.FieldGroup;
22
import com.vaadin.server.FontAwesome;
23
import com.vaadin.ui.Button;
24
import com.vaadin.ui.Component;
25
import com.vaadin.ui.CssLayout;
26
import com.vaadin.ui.Field;
27
import com.vaadin.ui.TextField;
28
import com.vaadin.ui.themes.ValoTheme;
29

    
30
import eu.etaxonomy.cdm.model.agent.Person;
31
import eu.etaxonomy.cdm.model.permission.CRUD;
32
import eu.etaxonomy.cdm.service.UserHelperAccess;
33
import eu.etaxonomy.cdm.vaadin.component.ButtonFactory;
34
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
35
import eu.etaxonomy.vaadin.component.CompositeCustomField;
36
import eu.etaxonomy.vaadin.component.SwitchButton;
37

    
38
/**
39
 * @author a.kohlbecker
40
 * @since May 11, 2017
41
 *
42
 */
43
public class PersonField extends CompositeCustomField<Person> {
44

    
45
    private static final long serialVersionUID = 8346575511284469356L;
46

    
47
    private static final String PRIMARY_STYLE = "v-person-field";
48

    
49
    private static final Pattern EMPTY_ENTITY_TITLE_CACHE_PATTERN = Pattern.compile("[a-zA-Z]+#[0-9]+<[a-f0-9\\-]+>");
50

    
51
    /**
52
     * do not allow entities which are having only <code>null</code> values in all fields
53
     * {@link #getValue()} would return <code>null</code> in this case.
54
     */
55
    boolean allowNewEmptyEntity = true;
56

    
57
    private LazyComboBox<Person> personSelect = new LazyComboBox<Person>(Person.class);
58

    
59
    private Button newPersonButton = ButtonFactory.CREATE_NEW.createButton();
60

    
61
    private BeanFieldGroup<Person> fieldGroup = new BeanFieldGroup<>(Person.class);
62

    
63
    enum Mode {
64
        CACHE_MODE, DETAILS_MODE;
65

    
66
        public String toCssClass() {
67
            return name().toLowerCase().replace("_", "-");
68
        }
69
    }
70

    
71
    private Mode currentMode = null;
72

    
73
    private float baseWidth = 100 / 9;
74

    
75
    private CssLayout root = new CssLayout();
76
    private CssLayout selectOrNewContainer = new CssLayout();
77

    
78
    private TextField titleCacheField = new TextFieldNFix();
79
    private TextField nomenclaturalTitleField = new TextFieldNFix();
80
    private Button nomenclaturalTitleButton = new Button();
81
    private CssLayout detailsContainer = new CssLayout();
82
    private TextField initialsField = new TextFieldNFix();
83
    private TextField givenNameField = new TextFieldNFix();
84
    private TextField familyNameField = new TextFieldNFix();
85
    private TextField prefixField = new TextFieldNFix();
86
    private TextField suffixField = new TextFieldNFix();
87
    private SwitchButton unlockSwitch = new SwitchButton();
88

    
89

    
90
    /**
91
     * @param caption
92
     */
93
    public PersonField(String caption) {
94

    
95
        this();
96
        setCaption(caption);
97
    }
98

    
99
    /**
100
     * @param caption
101
     */
102
    public PersonField() {
103

    
104
        root.setPrimaryStyleName(PRIMARY_STYLE);
105

    
106
        // select existing or create new person
107
        addStyledComponents(personSelect, newPersonButton);
108
        personSelect.addValueChangeListener(e -> {
109
            if(personSelect.getValue() != null){
110
                setValue(personSelect.getValue());
111
//                 personSelect.clear();
112
            }
113
        });
114

    
115
        selectOrNewContainer.addComponents(personSelect, newPersonButton);
116
        newPersonButton.addClickListener(e -> createNewPerson());
117

    
118
        // edit person
119
        addStyledComponent(titleCacheField);
120
        addStyledComponents(initialsField);
121
        addStyledComponent(givenNameField);
122
        addStyledComponent(familyNameField);
123
        addStyledComponent(prefixField);
124
        addStyledComponent(suffixField);
125
        addStyledComponent(unlockSwitch);
126
        addStyledComponent(nomenclaturalTitleField);
127
        addStyledComponent(nomenclaturalTitleButton);
128

    
129
        addSizedComponent(root);
130
    }
131

    
132
    /**
133
     *
134
     */
135
    private void checkUserPermissions(Person newValue) {
136
        boolean userCanEdit = newValue == null || !newValue.isPersited() || UserHelperAccess.userHelper().userHasPermission(newValue, "DELETE", "UPDATE");
137
        setEnabled(userCanEdit);
138
    }
139

    
140
    private void setMode(Mode mode){
141
        if(mode.equals(currentMode)){
142
            return;
143
        }
144
        if(currentMode != null){
145
            String removeMode = currentMode.toCssClass();
146
            root.removeStyleName(removeMode);
147
        }
148
        String newMode = mode.toCssClass();
149
        root.addStyleName(newMode);
150
        currentMode = mode;
151
    }
152

    
153

    
154
    /**
155
     * {@inheritDoc}
156
     */
157
    @Override
158
    protected Component initContent() {
159

    
160
        selectOrNewContainer.setWidth(100, Unit.PERCENTAGE);
161
        personSelect.setWidthUndefined();
162

    
163
        root.addComponent(titleCacheField);
164
        root.addComponent(unlockSwitch);
165
        root.addComponent(selectOrNewContainer);
166

    
167
        titleCacheField.setWidth(100, Unit.PERCENTAGE);
168
        titleCacheField.setDescription("Bibliographic title");
169

    
170
        prefixField.setWidth(baseWidth, Unit.PERCENTAGE);
171
        prefixField.setInputPrompt("Prefix");
172
        prefixField.setDescription("Prefix");
173

    
174
        initialsField.setWidth(baseWidth, Unit.PERCENTAGE);
175
        initialsField.setInputPrompt("Initials");
176
        initialsField.setDescription("Initials");
177

    
178
        givenNameField.setWidth(baseWidth * 3, Unit.PERCENTAGE);
179
        givenNameField.setInputPrompt("Other/given names");
180
        givenNameField.setDescription("Other/given names");
181

    
182
        familyNameField.setWidth(baseWidth * 3, Unit.PERCENTAGE);
183
        familyNameField.setInputPrompt("Family name");
184
        familyNameField.setDescription("Family name");
185

    
186
        suffixField.setWidth(baseWidth, Unit.PERCENTAGE);
187
        suffixField.setInputPrompt("Suffix");
188
        suffixField.setDescription("Suffix");
189

    
190
        detailsContainer.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
191
        detailsContainer.addComponent(prefixField);
192
        detailsContainer.addComponent(initialsField);
193
        detailsContainer.addComponent(givenNameField);
194
        detailsContainer.addComponent(familyNameField);
195
        detailsContainer.addComponent(suffixField);
196
        root.addComponent(detailsContainer);
197

    
198
        nomenclaturalTitleButton.setHeight(22, Unit.PIXELS);
199
        nomenclaturalTitleButton.setDescription("Show the nomenclatural title cache.");
200
        nomenclaturalTitleButton.addClickListener( e -> {
201
            nomenclaturalTitleField.setVisible(true || !nomenclaturalTitleField.isVisible());
202
            nomenclaturalTitleButtonChooseIcon();
203
            if(nomenclaturalTitleField.isVisible()){
204
                nomenclaturalTitleField.focus();
205
            }
206
        });
207
        // nomenclaturalTitleField.setCaption("Nomenclatural title");
208
        nomenclaturalTitleField.setDescription("Nomenclatural title");
209
        nomenclaturalTitleField.addStyleName("nomenclatural-title");
210
        nomenclaturalTitleField.setWidth(100, Unit.PERCENTAGE);
211
//        nomenclaturalTitleField.addValueChangeListener( e -> {
212
//            if(e.getProperty().getValue() != null && ((String)e.getProperty().getValue()).isEmpty()){
213
//
214
//            }
215
//        });
216

    
217
        root.addComponent(nomenclaturalTitleField);
218

    
219
        unlockSwitch.addValueChangeListener(e -> {
220
            if(refreshMode()){
221
                switch (currentMode) {
222
                    case CACHE_MODE:
223
                        titleCacheField.focus();
224
                        break;
225
                    case DETAILS_MODE:
226
                        givenNameField.focus();
227
                        break;
228
                    default:
229
                        break;
230

    
231
                }
232
            }
233
        });
234
        unlockSwitch.setValueSetLister(e -> {
235
            refreshMode();
236
        });
237

    
238
        addDefaultStyles();
239
        setMode(Mode.DETAILS_MODE);
240

    
241
        fieldGroup.bind(titleCacheField, "titleCache");
242
        fieldGroup.bind(prefixField, "prefix");
243
        fieldGroup.bind(initialsField, "initials");
244
        fieldGroup.bind(givenNameField, "givenName");
245
        fieldGroup.bind(familyNameField, "familyName");
246
        fieldGroup.bind(suffixField, "suffix");
247
        fieldGroup.bind(unlockSwitch, "protectedTitleCache");
248
        fieldGroup.bind(nomenclaturalTitleField, "nomenclaturalTitle");
249
        fieldGroup.setBuffered(false);
250

    
251
        updateVisibilities(getValue());
252

    
253
        return root;
254
    }
255

    
256
    /**
257
     *
258
     */
259
    protected void nomenclaturalTitleButtonChooseIcon() {
260
        nomenclaturalTitleButton.setIcon(true || nomenclaturalTitleField.isVisible() ? FontAwesome.ANGLE_UP : FontAwesome.ELLIPSIS_H);
261
    }
262

    
263
    /**
264
     *
265
     * @return true if the mode has changed
266
     */
267
    protected boolean refreshMode() {
268
        Mode lastMode = currentMode;
269
        setMode(unlockSwitch.getValue() ? Mode.CACHE_MODE: Mode.DETAILS_MODE);
270
        return !lastMode.equals(currentMode);
271
    }
272

    
273
    /**
274
     * {@inheritDoc}
275
     */
276
    @Override
277
    public Class<? extends Person> getType() {
278
        return Person.class;
279
    }
280

    
281
    private void createNewPerson(){
282
        Person p = Person.NewInstance();
283
        setValue(p);
284
    }
285

    
286
    @Override
287
    public void setValue(Person person){
288
        super.setValue(person);
289
        if(person != null && person.getId() != 0){
290
            personSelect.setValue(person);
291
        }
292
    }
293

    
294
    /**
295
     * {@inheritDoc}
296
     */
297
    @Override
298
    protected void setInternalValue(Person newValue) {
299

    
300
        super.setInternalValue(newValue);
301
        fieldGroup.setItemDataSource(newValue);
302
        checkUserPermissions(newValue);
303
        updateVisibilities(newValue);
304
    }
305

    
306
    /**
307
     *
308
     */
309
    private void updateVisibilities(Person person) {
310

    
311
        selectOrNewContainer.setVisible(person == null);
312

    
313
        detailsContainer.setVisible(person != null);
314
        unlockSwitch.setVisible(person != null);
315
        titleCacheField.setVisible(person != null);
316
        String nomTitle = nomenclaturalTitleField.getValue();
317
        boolean isEmptyItemTitle = nomTitle == null || EMPTY_ENTITY_TITLE_CACHE_PATTERN.matcher(nomTitle).matches();
318
        boolean nomTitleEqualsTitleCache = nomTitle != null && nomTitle.equals(titleCacheField.getValue());
319
        nomenclaturalTitleField.setVisible( !isEmptyItemTitle && !nomTitleEqualsTitleCache);
320
        nomenclaturalTitleButtonChooseIcon();
321

    
322
    }
323

    
324
    @Override
325
    protected void addDefaultStyles(){
326
        titleCacheField.addStyleName("cache-field");
327
        detailsContainer.addStyleName("details-fields");
328
        unlockSwitch.addStyleName(Switch.DOM_STYLE);
329
        nomenclaturalTitleButton.addStyleName(ValoTheme.BUTTON_BORDERLESS_COLORED + " center-h");
330
    }
331

    
332
    /**
333
     * {@inheritDoc}
334
     */
335
    @Override
336
    public Optional<FieldGroup> getFieldGroup() {
337
        return Optional.of(fieldGroup);
338
    }
339

    
340

    
341
    /**
342
     * {@inheritDoc}
343
     */
344
    @Override
345
    protected List<Field> nullValueCheckIgnoreFields() {
346

    
347
        List<Field>ignoreFields = super.nullValueCheckIgnoreFields();
348
        ignoreFields.add(unlockSwitch);
349

    
350
        if(unlockSwitch.getValue().booleanValue() == false){
351
            Person value = getValue();
352
            if(value != null && value.getId() == 0){
353
                // only if the entity is unsaved!
354
                ignoreFields.add(titleCacheField);
355
                titleCacheField.setValue(null);
356
            }
357
        }
358
        return ignoreFields;
359
    }
360

    
361
    @Override
362
    public void commit() throws SourceException, InvalidValueException {
363

    
364
        String lastNomenclaturalTitle = null;
365
        if(getValue() != null){
366
           lastNomenclaturalTitle = getValue().getNomenclaturalTitle();
367
        }
368
        super.commit();
369

    
370
        Person bean =  getValue();
371

    
372
        if(bean != null && !isReadOnly()){
373
            String nomTitle = nomenclaturalTitleField.getValue();
374
            if(nomTitle != null && nomTitle != lastNomenclaturalTitle && nomTitle.equals(titleCacheField.getValue())){
375
                // no point having a nomenclaturalTitle if it is equal to the titleCache
376
                bean.setNomenclaturalTitle(null);
377
            }
378
            boolean isUnsaved = bean.getId() == 0;
379
            if(isUnsaved && !(hasNullContent() && !allowNewEmptyEntity)){
380
                UserHelperAccess.userHelper().createAuthorityForCurrentUser(bean, EnumSet.of(CRUD.UPDATE, CRUD.DELETE), null);
381
            }
382
        }
383
    }
384

    
385
    /**
386
     * {@inheritDoc}
387
     *
388
     * @return returns <code>null</code> in case the edited entity is unsaved and if
389
     * it only has null values.
390
     */
391
    @Override
392
    public Person getValue() {
393
        Person bean = super.getValue();
394
        if(bean == null){
395
            return null;
396
        }
397
        return bean;
398
    }
399

    
400
    /**
401
     * @return the personSelect
402
     */
403
    public LazyComboBox<Person> getPersonSelect() {
404
        return personSelect;
405
    }
406

    
407
    /**
408
     * @param personSelect the personSelect to set
409
     */
410
    public void setPersonSelect(LazyComboBox<Person> personSelect) {
411
        this.personSelect = personSelect;
412
    }
413

    
414
    /**
415
     * @return the allowNewEmptyEntity
416
     */
417
    public boolean isAllowNewEmptyEntity() {
418
        return allowNewEmptyEntity;
419
    }
420

    
421
    /**
422
     * @param allowNewEmptyEntity the allowNewEmptyEntity to set
423
     */
424
    public void setAllowNewEmptyEntity(boolean allowNewEmptyEntity) {
425
        this.allowNewEmptyEntity = allowNewEmptyEntity;
426
    }
427

    
428

    
429

    
430
}
(5-5/8)