Project

General

Profile

Download (12.6 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

    
14
import org.vaadin.viritin.fields.LazyComboBox;
15

    
16
import com.vaadin.data.Validator.InvalidValueException;
17
import com.vaadin.data.fieldgroup.BeanFieldGroup;
18
import com.vaadin.data.fieldgroup.FieldGroup;
19
import com.vaadin.data.util.BeanItem;
20
import com.vaadin.server.FontAwesome;
21
import com.vaadin.server.UserError;
22
import com.vaadin.ui.Button;
23
import com.vaadin.ui.Component;
24
import com.vaadin.ui.CssLayout;
25
import com.vaadin.ui.Field;
26
import com.vaadin.ui.themes.ValoTheme;
27

    
28
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
29
import eu.etaxonomy.cdm.model.agent.AgentBase;
30
import eu.etaxonomy.cdm.model.agent.Person;
31
import eu.etaxonomy.cdm.model.agent.Team;
32
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
33
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
34
import eu.etaxonomy.cdm.service.CdmFilterablePagingProvider;
35
import eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityReloader;
36
import eu.etaxonomy.cdm.vaadin.permission.UserHelper;
37
import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
38
import eu.etaxonomy.cdm.vaadin.util.converter.CdmBaseDeproxyConverter;
39
import eu.etaxonomy.cdm.vaadin.view.name.CachingPresenter;
40
import eu.etaxonomy.vaadin.component.CompositeCustomField;
41
import eu.etaxonomy.vaadin.component.EntityFieldInstantiator;
42
import eu.etaxonomy.vaadin.component.ReloadableLazyComboBox;
43
import eu.etaxonomy.vaadin.component.SwitchableTextField;
44
import eu.etaxonomy.vaadin.component.ToManyRelatedEntitiesListSelect;
45

    
46
/**
47
 * @author a.kohlbecker
48
 * @since May 11, 2017
49
 *
50
 */
51
public class TeamOrPersonField extends CompositeCustomField<TeamOrPersonBase<?>> {
52

    
53
    private static final long serialVersionUID = 660806402243118112L;
54

    
55
    private static final String PRIMARY_STYLE = "v-team-or-person-field";
56

    
57
    private CssLayout root = new CssLayout();
58
    private CssLayout toolBar= new CssLayout();
59
    private CssLayout compositeWrapper = new CssLayout();
60

    
61
    private ReloadableLazyComboBox<TeamOrPersonBase> teamOrPersonSelect = new ReloadableLazyComboBox<TeamOrPersonBase>(TeamOrPersonBase.class);
62

    
63
    private Button selectConfirmButton = new Button("OK");
64
    private Button removeButton = new Button(FontAwesome.REMOVE);
65
    private Button personButton = new Button(FontAwesome.USER);
66
    private Button teamButton = new Button(FontAwesome.USERS);
67

    
68
    // Fields for case when value is a Person
69
    private PersonField personField = new PersonField();
70

    
71
    // Fields for case when value is a Team
72
    private SwitchableTextField titleField = new SwitchableTextField("Team (bibliographic)");
73
    private SwitchableTextField nomenclaturalTitleField = new SwitchableTextField("Team (nomenclatural)");
74
    private ToManyRelatedEntitiesListSelect<Person, PersonField> personsListEditor = new ToManyRelatedEntitiesListSelect<Person, PersonField>(Person.class, PersonField.class, "Team members");
75

    
76
    private BeanFieldGroup<Team> fieldGroup  = new BeanFieldGroup<>(Team.class);
77

    
78
    private CdmFilterablePagingProvider<AgentBase, Person> pagingProviderPerson;
79

    
80
    private TeamOrPersonBaseCaptionGenerator.CacheType cacheType;
81

    
82
    public TeamOrPersonField(String caption, TeamOrPersonBaseCaptionGenerator.CacheType cacheType){
83

    
84
        setCaption(caption);
85

    
86
        this.cacheType = cacheType;
87
        teamOrPersonSelect.setCaptionGenerator(new TeamOrPersonBaseCaptionGenerator<TeamOrPersonBase>(cacheType));
88

    
89

    
90
        addStyledComponent(teamOrPersonSelect);
91
        addStyledComponent(personField);
92
        addStyledComponent(titleField);
93
        addStyledComponent(nomenclaturalTitleField);
94
        addStyledComponent(personsListEditor);
95
        addStyledComponents(selectConfirmButton, removeButton, personButton, teamButton);
96

    
97

    
98
        addSizedComponent(root);
99
        addSizedComponent(compositeWrapper);
100
        addSizedComponent(personField);
101
        addSizedComponent(titleField);
102
        addSizedComponent(nomenclaturalTitleField);
103
        addSizedComponent(personsListEditor);
104

    
105
        setConverter(new CdmBaseDeproxyConverter<TeamOrPersonBase<?>>());
106

    
107
        updateToolBarButtonStates();
108
    }
109

    
110
    /**
111
     * {@inheritDoc}
112
     */
113
    @Override
114
    protected Component initContent() {
115

    
116
        teamOrPersonSelect.addValueChangeListener(e -> {
117
            selectConfirmButton.setEnabled(teamOrPersonSelect.getValue() != null);
118
            selectConfirmButton.addStyleName(ValoTheme.BUTTON_PRIMARY);
119
        });
120
        teamOrPersonSelect.setWidthUndefined();
121

    
122
        selectConfirmButton.setEnabled(teamOrPersonSelect.getValue() != null);
123
        selectConfirmButton.addClickListener(e -> {
124
            setValue(teamOrPersonSelect.getValue());
125
            teamOrPersonSelect.clear();
126
            updateToolBarButtonStates();
127
        });
128
        removeButton.addClickListener(e -> {
129
            setValue(null);
130
            updateToolBarButtonStates();
131
        });
132
        removeButton.setDescription("Remove");
133

    
134
        personButton.addClickListener(e -> {
135
            setValue(Person.NewInstance()); // FIXME add SelectField or open select dialog, use ToOneSelect field!!
136
            updateToolBarButtonStates();
137
        });
138
        personButton.setDescription("Add person");
139
        teamButton.addClickListener(e -> {
140
            setValue(Team.NewInstance()); // FIXME add SelectField or open select dialog, use ToOneSelect field!!
141
            updateToolBarButtonStates();
142
        });
143
        teamButton.setDescription("Add team");
144

    
145
        toolBar.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP + " toolbar");
146
        toolBar.addComponents(teamOrPersonSelect, selectConfirmButton,  removeButton, personButton, teamButton);
147

    
148
        compositeWrapper.setStyleName("margin-wrapper");
149
        compositeWrapper.addComponent(toolBar);
150

    
151
        root.setPrimaryStyleName(PRIMARY_STYLE);
152
        root.addComponent(compositeWrapper);
153
        return root;
154
    }
155

    
156
    /**
157
     * {@inheritDoc}
158
     */
159
    @Override
160
    public Class getType() {
161
        return TeamOrPersonBase.class;
162
    }
163

    
164
    private void updateToolBarButtonStates(){
165
        TeamOrPersonBase<?> val = getInternalValue();
166
        boolean userCanCreate = UserHelper.fromSession().userHasPermission(Person.class, "CREATE");
167

    
168
        teamOrPersonSelect.setVisible(val == null);
169
        selectConfirmButton.setVisible(val == null);
170
        removeButton.setVisible(val != null);
171
        personButton.setEnabled(userCanCreate && val == null);
172
        teamButton.setEnabled(userCanCreate && val == null);
173
    }
174

    
175
    /**
176
     * {@inheritDoc}
177
     */
178
    @Override
179
    protected void setInternalValue(TeamOrPersonBase<?> newValue) {
180

    
181
        super.setInternalValue(newValue);
182

    
183
        newValue = HibernateProxyHelper.deproxy(newValue);
184

    
185
        compositeWrapper.removeAllComponents();
186
        compositeWrapper.addComponent(toolBar);
187

    
188
        if(newValue != null) {
189

    
190
            if(Person.class.isAssignableFrom(newValue.getClass())){
191
                // value is a Person:
192
                compositeWrapper.addComponent(personField);
193

    
194
                personField.setValue((Person) newValue);
195
                personField.registerParentFieldGroup(fieldGroup);
196

    
197
            }
198
            else if(Team.class.isAssignableFrom(newValue.getClass())){
199
                // otherwise it a Team
200

    
201
                compositeWrapper.addComponents(titleField, nomenclaturalTitleField, personsListEditor);
202

    
203
                titleField.bindTo(fieldGroup, "titleCache", "protectedTitleCache");
204
                nomenclaturalTitleField.bindTo(fieldGroup, "nomenclaturalTitle", "protectedNomenclaturalTitleCache");
205
                fieldGroup.setItemDataSource(new BeanItem<Team>((Team)newValue));
206
                fieldGroup.bind(personsListEditor, "teamMembers"); // here personField is set readonly since setTeamMembers does not exist
207
                personsListEditor.setReadOnly(false); // fixing the readonly state
208

    
209
                personsListEditor.registerParentFieldGroup(fieldGroup);
210

    
211
            } else {
212
                setComponentError(new UserError("TeamOrPersonField Error: Unsupported value type: " + newValue.getClass().getName()));
213
            }
214

    
215
        }
216

    
217
        updateToolBarButtonStates();
218
    }
219

    
220
    private void checkUserPermissions(TeamOrPersonBase<?> newValue) {
221
        boolean userCanEdit = UserHelper.fromSession().userHasPermission(newValue, "DELETE", "UPDATE");
222
        setEnabled(userCanEdit);
223
        personsListEditor.setEnabled(userCanEdit);
224
    }
225

    
226
    /**
227
     * {@inheritDoc}
228
     */
229
    @Override
230
    protected void addDefaultStyles() {
231
        // no default styles here
232
    }
233

    
234
    /**
235
     * {@inheritDoc}
236
     */
237
    @Override
238
    public FieldGroup getFieldGroup() {
239
        return fieldGroup;
240
    }
241

    
242
    public Component[] getCachFields(){
243
        return new Component[]{titleField, nomenclaturalTitleField};
244
    }
245

    
246
    /**
247
     * @return the teamOrPersonSelect
248
     */
249
    public LazyComboBox<TeamOrPersonBase> getTeamOrPersonSelect() {
250
        return teamOrPersonSelect;
251
    }
252

    
253
    /**
254
     * {@inheritDoc}
255
     */
256
    @SuppressWarnings("unchecked")
257
    @Override
258
    public void commit() throws SourceException, InvalidValueException {
259

    
260
        //need to commit the subfields propagation through the fielGroups is not enough
261
        personField.commit();
262
        personsListEditor.commit();
263
        super.commit();
264

    
265
        TeamOrPersonBase<?> bean = getValue();
266
        if(bean != null && bean instanceof Team){
267

    
268
            boolean isUnsaved = bean.getId() == 0;
269
            if(isUnsaved){
270
                UserHelper.fromSession().createAuthorityForCurrentUser(bean, EnumSet.of(CRUD.UPDATE, CRUD.DELETE), null);
271
            }
272
        }
273

    
274
        if(hasNullContent()){
275
            getPropertyDataSource().setValue(null);
276
            setValue(null);
277

    
278
        }
279
    }
280

    
281
    /**
282
     * {@inheritDoc}
283
     */
284
    @Override
285
    protected List<Field> nullValueCheckIgnoreFields() {
286

    
287
        List<Field> ignoreFields =  super.nullValueCheckIgnoreFields();
288
        ignoreFields.add(personField);
289
        ignoreFields.add(nomenclaturalTitleField.getUnlockSwitch());
290
        if(nomenclaturalTitleField.getUnlockSwitch().getValue().booleanValue() == false){
291
            ignoreFields.add(nomenclaturalTitleField.getTextField());
292
        }
293
        ignoreFields.add(titleField.getUnlockSwitch());
294
        if(titleField.getUnlockSwitch().getValue().booleanValue() == false){
295
            ignoreFields.add(titleField.getTextField());
296
        }
297
        return ignoreFields;
298
    }
299

    
300
    /**
301
     * {@inheritDoc}
302
     */
303
    @Override
304
    public boolean hasNullContent() {
305

    
306
        TeamOrPersonBase<?> bean = getValue();
307
        if(bean == null) {
308
            return true;
309
        }
310
        if(bean instanceof Team){
311
            // --- Team
312
            return super.hasNullContent();
313
        } else {
314
            // --- Person
315
            return personField.hasNullContent();
316
        }
317
    }
318

    
319
    public void setFilterableTeamPagingProvider(CdmFilterablePagingProvider<AgentBase, TeamOrPersonBase> pagingProvider, CachingPresenter cachingPresenter){
320
        teamOrPersonSelect.loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
321
        ToOneRelatedEntityReloader<TeamOrPersonBase> teamOrPersonReloader = new ToOneRelatedEntityReloader<TeamOrPersonBase>(teamOrPersonSelect, cachingPresenter);
322
        teamOrPersonSelect.addValueChangeListener(teamOrPersonReloader );
323
    }
324

    
325
    public void setFilterablePersonPagingProvider(CdmFilterablePagingProvider<AgentBase, Person> pagingProvider, CachingPresenter cachingPresenter){
326

    
327
        teamOrPersonSelect.addValueChangeListener(new ToOneRelatedEntityReloader<TeamOrPersonBase>(teamOrPersonSelect, cachingPresenter));
328

    
329
        personsListEditor.setEntityFieldInstantiator(new EntityFieldInstantiator<PersonField>() {
330

    
331
            @Override
332
            public PersonField createNewInstance() {
333
                PersonField f = new PersonField();
334
                f.setAllowNewEmptyEntity(true); // otherwise new entities can not be added to the personsListEditor
335
                f.getPersonSelect().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
336
                f.getPersonSelect().setCaptionGenerator(new TeamOrPersonBaseCaptionGenerator<Person>(cacheType));
337
                f.getPersonSelect().addValueChangeListener(new ToOneRelatedEntityReloader<Person>(f.getPersonSelect(), cachingPresenter));
338
                return f;
339
            }
340
        });
341
    }
342

    
343
    /**
344
     * {@inheritDoc}
345
     */
346
    @Override
347
    public void setReadOnly(boolean readOnly) {
348
        super.setReadOnly(readOnly);
349
        setDeepReadOnly(readOnly, getContent());
350
    }
351

    
352

    
353

    
354
}
(4-4/5)