Project

General

Profile

« Previous | Next » 

Revision 19ba9005

Added by Andreas Kohlbecker over 6 years ago

fix #7135 TeamOrPersonField allows selecting from existing Persons and Teams

View differences:

src/main/java/eu/etaxonomy/cdm/service/CdmFilterablePagingProvider.java
25 25
 * @since Jun 7, 2017
26 26
 *
27 27
 */
28
public class CdmFilterablePagingProvider<T extends IdentifiableEntity> implements FilterablePagingProvider<T>, FilterableCountProvider {
28
public class CdmFilterablePagingProvider<T extends IdentifiableEntity, V extends T> implements FilterablePagingProvider<V>, FilterableCountProvider {
29 29

  
30 30
    private int pageSize = 20;
31 31

  
32 32
    private IIdentifiableEntityService<T> service;
33 33

  
34
    private Class<V> type = null;
35

  
34 36
    private MatchMode matchMode = MatchMode.ANYWHERE;
35 37

  
36 38
    private List<OrderHint> orderHints = OrderHint.ORDER_BY_TITLE_CACHE.asList();
......
67 69
    /**
68 70
     * With defaults for matchMode = MatchMode.ANYWHERE and orderHints = OrderHint.ORDER_BY_TITLE_CACHE
69 71
     *
70
     * @param service
71 72
     */
72 73
    public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service) {
73
        super();
74
        this.service = service;
74
        this(service, null);
75 75
    }
76 76

  
77 77
    /**
78
     * @param service
79
     * @param matchMode
80
     * @param orderHints
78
     * With defaults for matchMode = MatchMode.ANYWHERE and orderHints = OrderHint.ORDER_BY_TITLE_CACHE
79
     *
81 80
     */
81
    public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, Class<V> type) {
82
        super();
83
        this.type = type;
84
        this.service = service;
85
    }
86

  
87

  
82 88
    public CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, MatchMode matchMode, List<OrderHint> orderHints) {
89
        this(service, null, matchMode, orderHints);
90
    }
91

  
92
    public <S extends T> CdmFilterablePagingProvider(IIdentifiableEntityService<T> service, Class<V> type, MatchMode matchMode, List<OrderHint> orderHints) {
83 93
        super();
94
        this.type = type;
84 95
        this.service = service;
85 96
        this.matchMode = matchMode;
86 97
        this.orderHints = orderHints;
......
90 101
     * {@inheritDoc}
91 102
     */
92 103
    @Override
93
    public List<T> findEntities(int firstRow, String filter) {
104
    public List<V> findEntities(int firstRow, String filter) {
94 105

  
95
        Pager<T> page = service.findByTitle(
96
                null,
106
        Pager<V> page = (Pager<V>) service.findByTitle(
107
                type,
97 108
                filter,
98 109
                matchMode,
99 110
                null,
......
111 122
    @Override
112 123
    public int size(String filter) {
113 124

  
114
        Pager<T> page = service.findByTitle(
115
                null,
125
        Pager<V> page = (Pager<V>) service.findByTitle(
126
                type,
116 127
                filter,
117 128
                matchMode,
118 129
                null,
src/main/java/eu/etaxonomy/cdm/vaadin/component/common/PersonField.java
12 12
import java.util.List;
13 13

  
14 14
import org.vaadin.teemu.switchui.Switch;
15
import org.vaadin.viritin.fields.LazyComboBox;
15 16

  
16 17
import com.vaadin.data.Validator.InvalidValueException;
17 18
import com.vaadin.data.fieldgroup.BeanFieldGroup;
18 19
import com.vaadin.data.fieldgroup.FieldGroup;
20
import com.vaadin.ui.Button;
19 21
import com.vaadin.ui.Component;
20 22
import com.vaadin.ui.CssLayout;
21 23
import com.vaadin.ui.Field;
......
45 47
     */
46 48
    boolean allowNewEmptyEntity = false;
47 49

  
50
    private LazyComboBox<Person> personSelect = new LazyComboBox<Person>(Person.class);
51

  
52
    private Button personSelectConfirmButton = new Button("OK");
53
    private Button newPersonButton = new Button("New");
54

  
48 55
    private BeanFieldGroup<Person> fieldGroup = new BeanFieldGroup<>(Person.class);
49 56

  
50 57
    enum Mode {
......
60 67
    private float baseWidth = 100 / 8;
61 68

  
62 69
    private CssLayout root = new CssLayout();
70
    private CssLayout selectOrNewContainer = new CssLayout();
71

  
63 72
    private TextField cacheField = new TextField();
64 73
    private CssLayout detailsContainer = new CssLayout();
65 74
    private TextField firstNameField = new TextField();
......
84 93

  
85 94
        root.setPrimaryStyleName(PRIMARY_STYLE);
86 95

  
96
        // select existing or create new person
97
        addStyledComponents(personSelect, personSelectConfirmButton, newPersonButton);
98
        personSelect.addValueChangeListener(e -> {
99
            if(personSelect.getValue() != null){
100
                personSelectConfirmButton.setEnabled(true);
101
            }
102
        });
103
        personSelectConfirmButton.setEnabled(false);
104
        personSelectConfirmButton.addClickListener(e -> {
105
            setValue(personSelect.getValue());
106
        });
107
        selectOrNewContainer.addComponents(personSelect, personSelectConfirmButton, newPersonButton);
108
        newPersonButton.addClickListener(e -> {
109
            setValue(Person.NewInstance());
110
        });
111

  
112
        // edit person
87 113
        addStyledComponent(cacheField);
88 114
        addStyledComponent(firstNameField);
89 115
        addStyledComponent(lastNameField);
......
92 118
        addStyledComponent(unlockSwitch);
93 119

  
94 120
        addSizedComponent(root);
95

  
96 121
    }
97 122

  
98 123
    /**
......
124 149
    @Override
125 150
    protected Component initContent() {
126 151

  
152
        selectOrNewContainer.setWidth(100, Unit.PERCENTAGE);
153
        personSelect.setWidthUndefined();
154

  
127 155
        root.addComponent(cacheField);
128 156
        root.addComponent(unlockSwitch);
157
        root.addComponent(selectOrNewContainer);
129 158

  
130 159
        cacheField.setWidth(100, Unit.PERCENTAGE);
131 160

  
......
178 207
        fieldGroup.bind(unlockSwitch, "protectedTitleCache");
179 208
        fieldGroup.setBuffered(false);
180 209

  
210
        updateVisibilities(getValue());
211

  
181 212
        return root;
182 213
    }
183 214

  
......
201 232

  
202 233
    @Override
203 234
    public void setValue(Person person){
204
        if(person == null){
205
            person = Person.NewInstance();
206
        }
235
//        if(person == null){
236
//            person = Person.NewInstance();
237
//        }
207 238
        super.setValue(person);
208 239
    }
209 240

  
......
212 243
     */
213 244
    @Override
214 245
    protected void setInternalValue(Person newValue) {
246

  
215 247
        super.setInternalValue(newValue);
216 248
        fieldGroup.setItemDataSource(newValue);
217 249
        checkUserPermissions(newValue);
250
        updateVisibilities(newValue);
251
    }
252

  
253
    /**
254
     *
255
     */
256
    private void updateVisibilities(Person person) {
257

  
258
        selectOrNewContainer.setVisible(person == null);
259

  
260
        detailsContainer.setVisible(person != null);
261
        unlockSwitch.setVisible(person != null);
262
        cacheField.setVisible(person != null);
263

  
218 264
    }
219 265

  
220 266
    @Override
......
284 330
        return bean;
285 331
    }
286 332

  
333
    /**
334
     * @return the personSelect
335
     */
336
    public LazyComboBox<Person> getPersonSelect() {
337
        return personSelect;
338
    }
339

  
340
    /**
341
     * @param personSelect the personSelect to set
342
     */
343
    public void setPersonSelect(LazyComboBox<Person> personSelect) {
344
        this.personSelect = personSelect;
345
    }
346

  
347
    /**
348
     * @return the allowNewEmptyEntity
349
     */
350
    public boolean isAllowNewEmptyEntity() {
351
        return allowNewEmptyEntity;
352
    }
353

  
354
    /**
355
     * @param allowNewEmptyEntity the allowNewEmptyEntity to set
356
     */
357
    public void setAllowNewEmptyEntity(boolean allowNewEmptyEntity) {
358
        this.allowNewEmptyEntity = allowNewEmptyEntity;
359
    }
360

  
361

  
362

  
287 363
}
src/main/java/eu/etaxonomy/cdm/vaadin/component/common/TeamOrPersonField.java
11 11
import java.util.EnumSet;
12 12
import java.util.List;
13 13

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

  
14 16
import com.vaadin.data.Validator.InvalidValueException;
15 17
import com.vaadin.data.fieldgroup.BeanFieldGroup;
16 18
import com.vaadin.data.fieldgroup.FieldGroup;
......
24 26
import com.vaadin.ui.themes.ValoTheme;
25 27

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

  
......
49 57
    private CssLayout toolBar= new CssLayout();
50 58
    private CssLayout compositeWrapper = new CssLayout();
51 59

  
60
    private LazyComboBox<TeamOrPersonBase> teamOrPersonSelect = new LazyComboBox<TeamOrPersonBase>(TeamOrPersonBase.class);
61

  
62
    private Button selectConfirmButton = new Button("OK");
52 63
    private Button removeButton = new Button(FontAwesome.REMOVE);
53 64
    private Button personButton = new Button(FontAwesome.USER);
54 65
    private Button teamButton = new Button(FontAwesome.USERS);
......
63 74

  
64 75
    private BeanFieldGroup<Team> fieldGroup  = new BeanFieldGroup<>(Team.class);
65 76

  
77
    private CdmFilterablePagingProvider<AgentBase, Person> pagingProviderPerson;
78

  
66 79
    public TeamOrPersonField(String caption){
67 80

  
68 81
        setCaption(caption);
69 82

  
83
        teamOrPersonSelect.setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TeamOrPersonBase>());
84

  
85

  
86
        addStyledComponent(teamOrPersonSelect);
70 87
        addStyledComponent(personField);
71 88
        addStyledComponent(titleField);
72 89
        addStyledComponent(nomenclaturalTitleField);
73 90
        addStyledComponent(personsListEditor);
74
        addStyledComponents(removeButton, personButton, teamButton);
91
        addStyledComponents(selectConfirmButton, removeButton, personButton, teamButton);
75 92

  
76 93

  
77 94
        addSizedComponent(root);
......
92 109
    @Override
93 110
    protected Component initContent() {
94 111

  
112
        teamOrPersonSelect.addValueChangeListener(e -> {
113
            selectConfirmButton.setEnabled(teamOrPersonSelect.getValue() != null);
114
        });
115
        teamOrPersonSelect.setWidthUndefined();
116

  
117
        selectConfirmButton.setEnabled(teamOrPersonSelect.getValue() != null);
118
        selectConfirmButton.addClickListener(e -> {
119
            setValue(teamOrPersonSelect.getValue());
120
            updateToolBarButtonStates();
121
        });
95 122
        removeButton.addClickListener(e -> {
96 123
            setValue(null);
97 124
            updateToolBarButtonStates();
......
110 137
        teamButton.setDescription("Add team");
111 138

  
112 139
        toolBar.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP + " toolbar");
113
        toolBar.addComponents(removeButton, personButton, teamButton);
140
        toolBar.addComponents(teamOrPersonSelect, selectConfirmButton,  removeButton, personButton, teamButton);
114 141

  
115 142
        compositeWrapper.setStyleName("margin-wrapper");
116 143
        compositeWrapper.addComponent(toolBar);
......
131 158
    private void updateToolBarButtonStates(){
132 159
        TeamOrPersonBase<?> val = getInternalValue();
133 160
        boolean userCanCreate = UserHelper.fromSession().userHasPermission(Person.class, "CREATE");
134
        removeButton.setEnabled(val != null);
161

  
162
        teamOrPersonSelect.setVisible(val == null);
163
        selectConfirmButton.setVisible(val == null);
164
        removeButton.setVisible(val != null);
135 165
        personButton.setEnabled(userCanCreate && val == null);
136 166
        teamButton.setEnabled(userCanCreate && val == null);
137 167
    }
......
149 179
        compositeWrapper.removeAllComponents();
150 180
        compositeWrapper.addComponent(toolBar);
151 181

  
152
        if(newValue == null) {
153
            return;
154
        }
182
        if(newValue != null) {
155 183

  
156
        if(Person.class.isAssignableFrom(newValue.getClass())){
157
            // value is a Person:
158
            compositeWrapper.addComponent(personField);
184
            if(Person.class.isAssignableFrom(newValue.getClass())){
185
                // value is a Person:
186
                compositeWrapper.addComponent(personField);
159 187

  
160
            personField.setValue((Person) newValue);
161
            personField.registerParentFieldGroup(fieldGroup);
188
                personField.setValue((Person) newValue);
189
                personField.registerParentFieldGroup(fieldGroup);
162 190

  
163
        }
164
        else if(Team.class.isAssignableFrom(newValue.getClass())){
165
            // otherwise it a Team
191
            }
192
            else if(Team.class.isAssignableFrom(newValue.getClass())){
193
                // otherwise it a Team
166 194

  
167
            compositeWrapper.addComponents(titleField, nomenclaturalTitleField, personsListEditor);
195
                compositeWrapper.addComponents(titleField, nomenclaturalTitleField, personsListEditor);
168 196

  
169
            titleField.bindTo(fieldGroup, "titleCache", "protectedTitleCache");
170
            nomenclaturalTitleField.bindTo(fieldGroup, "nomenclaturalTitle", "protectedNomenclaturalTitleCache");
171
            fieldGroup.setItemDataSource(new BeanItem<Team>((Team)newValue));
172
            fieldGroup.bind(personsListEditor, "teamMembers");
197
                titleField.bindTo(fieldGroup, "titleCache", "protectedTitleCache");
198
                nomenclaturalTitleField.bindTo(fieldGroup, "nomenclaturalTitle", "protectedNomenclaturalTitleCache");
199
                fieldGroup.setItemDataSource(new BeanItem<Team>((Team)newValue));
200
                fieldGroup.bind(personsListEditor, "teamMembers"); // here personField is set readonly since setTeamMembers does not exist
201
                personsListEditor.setReadOnly(false); // fixing the readonly state
173 202

  
174
            personsListEditor.registerParentFieldGroup(fieldGroup);
203
                personsListEditor.registerParentFieldGroup(fieldGroup);
175 204

  
205
            } else {
206
                setComponentError(new UserError("TeamOrPersonField Error: Unsupported value type: " + newValue.getClass().getName()));
207
            }
176 208

  
177
        } else {
178
            setComponentError(new UserError("TeamOrPersonField Error: Unsupported value type: " + newValue.getClass().getName()));
179 209
        }
180 210

  
181 211
        updateToolBarButtonStates();
......
207 237
        return new Component[]{titleField, nomenclaturalTitleField};
208 238
    }
209 239

  
240
    /**
241
     * @return the teamOrPersonSelect
242
     */
243
    public LazyComboBox<TeamOrPersonBase> getTeamOrPersonSelect() {
244
        return teamOrPersonSelect;
245
    }
246

  
210 247
    /**
211 248
     * {@inheritDoc}
212 249
     */
......
272 309
        }
273 310
    }
274 311

  
312
    public void setFilterableTeamPagingProvider(CdmFilterablePagingProvider<AgentBase, TeamOrPersonBase> pagingProvider, CachingPresenter cachingPresenter){
313
        teamOrPersonSelect.loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
314
        ToOneRelatedEntityReloader<TeamOrPersonBase> teamOrPersonReloader = new ToOneRelatedEntityReloader<TeamOrPersonBase>(teamOrPersonSelect, cachingPresenter);
315
        teamOrPersonSelect.addValueChangeListener(teamOrPersonReloader );
316
    }
317

  
318
    public void setFilterablePersonPagingProvider(CdmFilterablePagingProvider<AgentBase, Person> pagingProvider, CachingPresenter cachingPresenter){
319

  
320
        teamOrPersonSelect.addValueChangeListener(new ToOneRelatedEntityReloader<TeamOrPersonBase>(teamOrPersonSelect, cachingPresenter));
321

  
322
        personsListEditor.setEntityFieldInstantiator(new EntityFieldInstantiator<PersonField>() {
323

  
324
            @Override
325
            public PersonField createNewInstance() {
326
                PersonField f = new PersonField();
327
                f.setAllowNewEmptyEntity(true); // otherwise new entities can not be added to the personsListEditor
328
                f.getPersonSelect().loadFrom(pagingProvider, pagingProvider, pagingProvider.getPageSize());
329
                f.getPersonSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<Person>());
330
                f.getPersonSelect().addValueChangeListener(new ToOneRelatedEntityReloader<Person>(f.getPersonSelect(), cachingPresenter));
331
                return f;
332
            }
333
        });
334
    }
335

  
275 336
}
src/main/java/eu/etaxonomy/cdm/vaadin/event/ToOneRelatedEntityReloader.java
8 8
*/
9 9
package eu.etaxonomy.cdm.vaadin.event;
10 10

  
11
import org.vaadin.viritin.fields.LazyComboBox;
12

  
13 11
import com.vaadin.data.Property.ValueChangeEvent;
14 12
import com.vaadin.data.Property.ValueChangeListener;
13
import com.vaadin.ui.Field;
15 14

  
16 15
import eu.etaxonomy.cdm.cache.EntityCache;
17 16
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
......
28 27

  
29 28
    private static final long serialVersionUID = -1141764783149024788L;
30 29

  
31
    LazyComboBox<CDM>  toOneRelatedEntityField;
30
    Field<CDM>  toOneRelatedEntityField;
32 31

  
33 32
    CachingPresenter cachingPresenter;
34 33

  
35
    public ToOneRelatedEntityReloader( LazyComboBox<CDM> toOneRelatedEntityField, CachingPresenter entityCache){
34
    public ToOneRelatedEntityReloader( Field<CDM> toOneRelatedEntityField, CachingPresenter entityCache){
36 35
        this.toOneRelatedEntityField = toOneRelatedEntityField;
37 36
        this.cachingPresenter = entityCache;
38 37
    }
......
56 55
            CDM cachedEntity = cache.find(value);
57 56
            if(cachedEntity == null){
58 57
                cache.add(value);
59
            } else if(cachedEntity != value){
58
            } else if(
59
                    // pure object comparison is not reliable since the entity may have been changed
60
                    cachedEntity.getId() == value.getId() && cachedEntity.getClass() == value.getClass()){
60 61
                toOneRelatedEntityField.removeValueChangeListener(this);
61 62
                toOneRelatedEntityField.setValue(null); // reset to trick equals check in vaadin
62 63
                toOneRelatedEntityField.setValue(cachedEntity);
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/SpecimenTypeDesignationWorkingsetEditorPresenter.java
132 132
        getView().getTypeDesignationsCollectionField().addElementAddedListener(e -> addTypeDesignation(e.getElement()));
133 133
        getView().getTypeDesignationsCollectionField().setEditorInstantiator(new AbstractElementCollection.Instantiator<SpecimenTypeDesignationDTORow>() {
134 134

  
135
            CdmFilterablePagingProvider<Collection> collectionPagingProvider = new CdmFilterablePagingProvider<Collection>(getRepo().getCollectionService());
135
            CdmFilterablePagingProvider<Collection, Collection> collectionPagingProvider = new CdmFilterablePagingProvider<Collection, Collection>(getRepo().getCollectionService());
136 136

  
137
            CdmFilterablePagingProvider<Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference>(getRepo().getReferenceService());
137
            CdmFilterablePagingProvider<Reference, Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference, Reference>(getRepo().getReferenceService());
138 138

  
139 139
            @Override
140 140
            public SpecimenTypeDesignationDTORow create() {
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/TaxonNameEditorPresenter.java
15 15
import org.apache.log4j.Logger;
16 16

  
17 17
import eu.etaxonomy.cdm.api.service.INameService;
18
import eu.etaxonomy.cdm.model.agent.AgentBase;
19
import eu.etaxonomy.cdm.model.agent.Person;
20
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
18 21
import eu.etaxonomy.cdm.model.common.TermType;
19 22
import eu.etaxonomy.cdm.model.name.Rank;
20 23
import eu.etaxonomy.cdm.model.name.TaxonName;
......
50 53
        getView().getRankSelect().setContainerDataSource(selectFieldFactory.buildBeanItemContainer(TermType.Rank));
51 54
        getView().getRankSelect().setItemCaptionPropertyId("label");
52 55

  
56
        CdmFilterablePagingProvider<AgentBase, TeamOrPersonBase> termOrPersonPagingProvider = new CdmFilterablePagingProvider<AgentBase, TeamOrPersonBase>(getRepo().getAgentService(), TeamOrPersonBase.class);
57
        CdmFilterablePagingProvider<AgentBase, Person> personPagingProvider = new CdmFilterablePagingProvider<AgentBase, Person>(getRepo().getAgentService(), Person.class);
58

  
59
        getView().getCombinationAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
60
        getView().getCombinationAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
61

  
62
        getView().getExCombinationAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
63
        getView().getExCombinationAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
64

  
65
        getView().getBasionymAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
66
        getView().getBasionymAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
67

  
68
        getView().getExBasionymAuthorshipField().setFilterableTeamPagingProvider(termOrPersonPagingProvider, this);
69
        getView().getExBasionymAuthorshipField().setFilterablePersonPagingProvider(personPagingProvider, this);
70

  
53 71
        getView().getNomReferenceCombobox().getSelect().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<Reference>());
54
        CdmFilterablePagingProvider<Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference>(getRepo().getReferenceService());
72
        CdmFilterablePagingProvider<Reference, Reference> referencePagingProvider = new CdmFilterablePagingProvider<Reference, Reference>(getRepo().getReferenceService());
55 73
        getView().getNomReferenceCombobox().loadFrom(referencePagingProvider, referencePagingProvider, referencePagingProvider.getPageSize());
56 74
        getView().getNomReferenceCombobox().getSelect().addValueChangeListener(new ToOneRelatedEntityButtonUpdater<Reference>(getView().getNomReferenceCombobox()));
57 75

  
58 76

  
59 77
        getView().getBasionymCombobox().setCaptionGenerator(new CdmTitleCacheCaptionGenerator<TaxonName>());
60
        CdmFilterablePagingProvider<TaxonName> namePagingProvider = new CdmFilterablePagingProvider<TaxonName>(getRepo().getNameService());
78
        CdmFilterablePagingProvider<TaxonName, TaxonName> namePagingProvider = new CdmFilterablePagingProvider<TaxonName, TaxonName>(getRepo().getNameService());
61 79
        getView().getBasionymCombobox().setPagingProviders(namePagingProvider, namePagingProvider, namePagingProvider.getPageSize());
62 80
    }
63 81

  
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/TaxonNamePopupEditor.java
93 93
        return "Name editor";
94 94
    }
95 95

  
96

  
97

  
98
    /**
99
     * {@inheritDoc}
100
     */
101
    @Override
102
    public int getWindowPixelWidth() {
103
        return 700;
104
    }
105

  
96 106
    /**
97 107
     * {@inheritDoc}
98 108
     */
......
117 127
    protected void initContent() {
118 128

  
119 129
        GridLayout grid = (GridLayout)getFieldLayout();
130
        grid.setSizeFull();
120 131
        grid.setSpacing(true);
121 132
        grid.setColumnExpandRatio(0, 0.3f);
122 133
        grid.setColumnExpandRatio(1, 0.3f);
......
360 371
        return rankSelect;
361 372
    }
362 373

  
374
    /**
375
     * @return the exBasionymAuthorshipField
376
     */
377
    @Override
378
    public TeamOrPersonField getExBasionymAuthorshipField() {
379
        return exBasionymAuthorshipField;
380
    }
381

  
382
    /**
383
     * @return the basionymAuthorshipField
384
     */
385
    @Override
386
    public TeamOrPersonField getBasionymAuthorshipField() {
387
        return basionymAuthorshipField;
388
    }
389

  
390
    /**
391
     * @return the combinationAuthorshipField
392
     */
393
    @Override
394
    public TeamOrPersonField getCombinationAuthorshipField() {
395
        return combinationAuthorshipField;
396
    }
397

  
398
    /**
399
     * @return the exCombinationAuthorshipField
400
     */
401
    @Override
402
    public TeamOrPersonField getExCombinationAuthorshipField() {
403
        return exCombinationAuthorshipField;
404
    }
405

  
406

  
407

  
363 408

  
364 409
}
src/main/java/eu/etaxonomy/cdm/vaadin/view/name/TaxonNamePopupEditorView.java
12 12

  
13 13
import eu.etaxonomy.cdm.model.name.TaxonName;
14 14
import eu.etaxonomy.cdm.model.reference.Reference;
15
import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
15 16
import eu.etaxonomy.vaadin.component.ToManyRelatedEntitiesComboboxSelect;
16 17
import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
17 18
import eu.etaxonomy.vaadin.mvp.ApplicationView;
......
35 36

  
36 37
    public ListSelect getRankSelect();
37 38

  
39
    /**
40
     * @return the exBasionymAuthorshipField
41
     */
42
    public TeamOrPersonField getExBasionymAuthorshipField();
43

  
44
    /**
45
     * @return the basionymAuthorshipField
46
     */
47
    public TeamOrPersonField getBasionymAuthorshipField();
48

  
49
    /**
50
     * @return the combinationAuthorshipField
51
     */
52
    public TeamOrPersonField getCombinationAuthorshipField();
53

  
54
    /**
55
     * @return the exCombinationAuthorshipField
56
     */
57
    public TeamOrPersonField getExCombinationAuthorshipField();
58

  
38 59
}
src/main/java/eu/etaxonomy/cdm/vaadin/view/registration/RegistrationWorkingsetPresenter.java
160 160
        loadWorkingSet(getView().getCitationID());
161 161
        getView().setWorkingset(workingset);
162 162

  
163
        CdmFilterablePagingProvider<TaxonName> pagingProvider = new CdmFilterablePagingProvider<TaxonName>(
163
        CdmFilterablePagingProvider<TaxonName, TaxonName> pagingProvider = new CdmFilterablePagingProvider<TaxonName, TaxonName>(
164 164
                getRepo().getNameService());
165 165
        CdmTitleCacheCaptionGenerator<TaxonName> titleCacheGenrator = new CdmTitleCacheCaptionGenerator<TaxonName>();
166 166
        getView().getAddExistingNameCombobox().setCaptionGenerator(titleCacheGenrator);
src/main/java/eu/etaxonomy/cdm/vaadin/view/registration/StartRegistrationPresenter.java
57 57

  
58 58
        super.onPresenterReady();
59 59

  
60
        CdmFilterablePagingProvider<Reference> pagingProvider = new CdmFilterablePagingProvider<Reference>(
60
        CdmFilterablePagingProvider<Reference, Reference> pagingProvider = new CdmFilterablePagingProvider<Reference, Reference>(
61 61
                getRepo().getReferenceService());
62 62
        CdmTitleCacheCaptionGenerator<Reference> titleCacheGenrator = new CdmTitleCacheCaptionGenerator<Reference>();
63 63
        getView().getReferenceCombobox().setCaptionGenerator(titleCacheGenrator);
src/main/java/eu/etaxonomy/vaadin/component/CompositeCustomField.java
162 162
                .filter(
163 163
                        f -> !nullValueCheckIgnore.contains(f)
164 164
                )
165
                .peek( f -> System.out.println("###> " + f.getCaption() + ": " + f.getValue()))
165
                //.peek( f -> System.out.println("###> " + f.getCaption() + ": " + f.getValue()))
166 166
                .allMatch(
167 167
                        f -> {
168 168
                            if(f instanceof CompositeCustomField){
......
211 211
    @Override
212 212
    public void setReadOnly(boolean readOnly) {
213 213
        super.setReadOnly(readOnly);
214
        setDeepReadOnly(readOnly, getContent());
214
        // setDeepReadOnly(readOnly, getContent());
215 215
    }
216 216

  
217 217
    /**
......
230 230
        }
231 231
    }
232 232

  
233
    @Override
234
    public String toString(){
235
        return this.getClass().getSimpleName() + ": " +
236
                ( getValue() != null ? getValue() : "null");
237
    }
233 238

  
234 239
}
src/main/java/eu/etaxonomy/vaadin/component/EntityFieldInstantiator.java
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.vaadin.component;
10

  
11
/**
12
 * @author a.kohlbecker
13
 * @since Dec 11, 2017
14
 *
15
 */
16
public abstract class EntityFieldInstantiator<F> {
17

  
18
    public abstract F createNewInstance();
19

  
20
}
src/main/java/eu/etaxonomy/vaadin/component/ToManyRelatedEntitiesListSelect.java
47 47

  
48 48
    private FieldGroup parentFieldGroup = null;
49 49

  
50
    Boolean valueInitiallyWasNull = null;
51

  
50 52
    protected boolean isOrderedCollection = false;
51 53

  
52 54
    private boolean withEditButton = false;
......
59 61

  
60 62
    private GridLayout grid = new GridLayout(GRID_COLS, 1);
61 63

  
64
    private EntityFieldInstantiator<F> entityFieldInstantiator;
65

  
62 66
    public  ToManyRelatedEntitiesListSelect(Class<V> itemType, Class<F> fieldType, String caption){
63 67
        this.fieldType = fieldType;
64 68
        this.itemType = itemType;
......
86 90
     */
87 91
    private void addRowAfter(F field) {
88 92

  
93
        List<V> nestedValues = getValueFromNestedFields();
94

  
95
        if(isOrderedCollection){
96

  
97
        } else {
98

  
99
        }
100

  
89 101
        Integer row = findRow(field);
90 102

  
91 103
        grid.insertRow(row + 1);
......
146 158
    }
147 159

  
148 160
    /**
149
     *
161
     * update Value is only called in turn of UI changes like adding, removing, swapping rows
150 162
     */
151
    protected void updateValue() {
163
    private void updateValue() {
152 164
        List<V> nestedValues = getValueFromNestedFields();
153 165
        List<V> beanList = getValue();
154 166
        beanList.clear();
155 167
        beanList.addAll(nestedValues);
156
        setInternalValue(beanList);
168
        setInternalValue(beanList, false);
157 169
    }
158 170

  
159 171
    /**
......
207 219
    @Override
208 220
    protected void setInternalValue(List<V> newValue) {
209 221

  
210
         grid.removeAllComponents();
211
         grid.setRows(1);
222
        setInternalValue(newValue, true);
223

  
224
    }
225

  
226
    protected void setInternalValue(List<V> newValue, boolean doUpdateFields) {
227

  
228
        super.setInternalValue(newValue);
229

  
230
        if(valueInitiallyWasNull == null){
231
            valueInitiallyWasNull = newValue == null;
232
        }
212 233

  
213 234
        if(newValue != null){
214
            super.setInternalValue(newValue);
215 235

  
216 236
            // newValue is already converted, need to use the original value from the data source
217 237
            isOrderedCollection = List.class.isAssignableFrom(getPropertyDataSource().getValue().getClass());
218 238

  
219
            int row = 0;
220
            if(newValue.size() > 0){
221
                for(V val : newValue){
222
                    row = addNewRow(row, val);
223
                }
224
            }
225 239
        }
226 240

  
227
        if(newValue == null || newValue.isEmpty()) {
228
            // add an empty row
241
        createFieldsForData();
242

  
243
    }
244

  
245
    private void createFieldsForData(){
246

  
247
        grid.removeAllComponents();
248
        grid.setRows(1);
249

  
250
        List<V> data = getValue();
251
        if(data == null || data.isEmpty()){
229 252
            addNewRow(0, null);
253
        } else {
254
            int row = 0;
255
            for(V val : data){
256
                row = addNewRow(row, val);
257
            }
230 258
        }
259

  
260
    }
261

  
262
    /**
263
     * Obtains the List of values directly from the nested fields and ignores the
264
     * value of the <code>propertyDataSource</code>. This is useful when the ToManyRelatedEntitiesListSelect
265
     * is operating on a transient field, in which case the property is considered being read only by vaadin
266
     * so that the commit is doing nothing.
267
     *
268
     * See also {@link AbstractCdmEditorPresenter#handleTransientProperties(DTO bean)}
269
     *
270
     * @return
271
     */
272
    public List<V> getValueFromNestedFields() {
273
        List<V> nestedValues = new ArrayList<>();
274
        for(F f : getNestedFields()) {
275
            logger.trace(
276
                    String.format("getValueFromNestedFields() - %s:%s",
277
                       f != null ? f.getClass().getSimpleName() : "null",
278
                       f != null && f.getValue() != null ? f.getValue() : "null"
279
            ));
280
            V value = f.getValue();
281
            if(f != null /*&& value != null*/){
282
                nestedValues.add(f.getValue());
283
            }
284
         }
285
        return nestedValues;
231 286
    }
232 287

  
233 288
    /**
......
238 293
    protected int addNewRow(int row, V val) {
239 294
        try {
240 295
            F field = newFieldInstance(val);
296
            field.addValueChangeListener(e -> {
297
                updateValue();
298
            });
241 299
            Property ds = getPropertyDataSource();
242 300
            if(ds != null){
243 301
                Object parentVal = ds.getValue();
......
331 389

  
332 390

  
333 391
    protected List<F> getNestedFields(){
392

  
334 393
        List<F> nestedFields = new ArrayList<>(grid.getRows());
335 394
        for(int r = 0; r < grid.getRows(); r++){
336 395
            F f = (F) grid.getComponent(GRID_X_FIELD, r);
......
351 410
     * @throws IllegalAccessException
352 411
     */
353 412
    protected F newFieldInstance(V val) throws InstantiationException, IllegalAccessException {
354
        F field = fieldType.newInstance();
413

  
414
        F field;
415
        if(entityFieldInstantiator != null){
416
            field = entityFieldInstantiator.createNewInstance();
417
        } else {
418
            field = fieldType.newInstance();
419
        }
420

  
355 421
        field.setWidth(100, Unit.PERCENTAGE);
356 422
        field.setValue(val);
423

  
357 424
        // TODO
358 425
        // when passing null as value the field must take care of creating a new
359 426
        // instance by overriding setValue() in future we could improve this by passing a
......
415 482
            f.commit();
416 483

  
417 484
        }
485
        /*
486
        List<V> list = (List<V>) getPropertyDataSource().getValue();
487

  
488
        Person p = Person.NewInstance();
489
        p.setTitleCache("Hacky", true);
490
        list.add((V) p);
491

  
492
        List<V> clonedList = new ArrayList<>(list);
493
        list.clear();
494
        for(V value : clonedList){
495
            if(value != null){
496
                list.add(value);
497
            }
498
        }
499
        //
418 500
        // calling super.commit() is useless if operating on a transient property!!
419 501
        super.commit();
420
    }
421

  
422
    /**
423
     * Obtains the List of values directly from the nested fields and ignores the
424
     * value of the <code>propertyDataSource</code>. This is useful when the ToManyRelatedEntitiesListSelect
425
     * is operating on a transient field, in which case the property is considered being read only by vaadin
426
     * so that the commit is doing nothing.
427
     *
428
     * See also {@link AbstractCdmEditorPresenter#handleTransientProperties(DTO bean)}
429
     *
430
     * @return
431
     */
432
    public List<V> getValueFromNestedFields() {
433
        List<V> nestedValues = new ArrayList<>();
434
        for(F f : getNestedFields()) {
435
            logger.trace(
436
                    String.format("getValueFromNestedFields() - %s:%s",
437
                       f != null ? f.getClass().getSimpleName() : "null",
438
                       f != null && f.getValue() != null ? f.getValue() : "null"
439
            ));
440
            V value = f.getValue();
441
            if(f != null && value != null){
442
                nestedValues.add(f.getValue());
443
            }
444
         }
445
        return nestedValues;
502
        if(getValue().isEmpty() && valueInitiallyWasNull){
503
            setPropertyDataSource(null);
504
        }
505
         */
446 506
    }
447 507

  
448 508
    /**
......
490 550
        return true;
491 551
    }
492 552

  
553
    /**
554
     * @return the enityFieldInstantiator
555
     */
556
    public EntityFieldInstantiator<F> getEntityFieldInstantiator() {
557
        return entityFieldInstantiator;
558
    }
559

  
560
    /**
561
     * @param enityFieldInstantiator the enityFieldInstantiator to set
562
     */
563
    public void setEntityFieldInstantiator(EntityFieldInstantiator<F> entityFieldInstantiator) {
564
        this.entityFieldInstantiator = entityFieldInstantiator;
565
    }
493 566

  
494 567

  
495 568
}
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractCdmEditorPresenter.java
15 15
import org.springframework.context.event.EventListener;
16 16

  
17 17
import eu.etaxonomy.cdm.api.service.IService;
18
import eu.etaxonomy.cdm.cache.CdmEntityCache;
19
import eu.etaxonomy.cdm.cache.EntityCache;
18 20
import eu.etaxonomy.cdm.model.common.CdmBase;
19 21
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
20 22
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;
21 23
import eu.etaxonomy.cdm.service.CdmStore;
22 24
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
23 25
import eu.etaxonomy.cdm.vaadin.security.UserHelper;
26
import eu.etaxonomy.cdm.vaadin.view.name.CachingPresenter;
24 27
import eu.etaxonomy.vaadin.mvp.event.EditorPreSaveEvent;
25 28
import eu.etaxonomy.vaadin.mvp.event.EditorSaveEvent;
26 29

  
......
31 34
 * @since Apr 5, 2017
32 35
 *
33 36
 */
34
public abstract class AbstractCdmEditorPresenter<DTO extends CdmBase, V extends ApplicationView<?>> extends AbstractEditorPresenter<DTO, V> {
37
public abstract class AbstractCdmEditorPresenter<DTO extends CdmBase, V extends ApplicationView<?>> extends AbstractEditorPresenter<DTO, V>
38
    implements CachingPresenter {
35 39

  
36 40
    private static final long serialVersionUID = 2218185546277084261L;
37 41

  
......
44 48
    protected EnumSet<CRUD> crud = null;
45 49

  
46 50

  
51
    private CdmEntityCache cache = null;
52

  
47 53
    public AbstractCdmEditorPresenter() {
48 54
        super();
49 55
        logger.trace(this._toString() + " constructor");
......
63 69
    @Override
64 70
    protected DTO loadBeanById(Object identifier) {
65 71

  
72
        DTO cdmEntitiy;
66 73
        if(identifier != null) {
67 74
            Integer integerID = (Integer)identifier;
68 75
            // CdmAuthority is needed before the bean is loaded into the session.
69 76
            // otherwise adding the authority to the user would cause a flush
70 77
            guaranteePerEntityCRUDPermissions(integerID);
71
            return loadCdmEntityById(integerID);
78
            cdmEntitiy = loadCdmEntityById(integerID);
72 79
        } else {
73
            DTO cdmEntitiy = loadCdmEntityById(null);
80
            cdmEntitiy = loadCdmEntityById(null);
74 81
            if(cdmEntitiy != null){
75 82
                guaranteePerEntityCRUDPermissions(cdmEntitiy);
76 83
            }
77
            return cdmEntitiy;
78 84
        }
79 85

  
86
        cache = new CdmEntityCache(cdmEntitiy);
87

  
88
        return cdmEntitiy;
80 89
    }
81 90

  
82 91

  
......
203 212

  
204 213
    }
205 214

  
215
    /**
216
     * {@inheritDoc}
217
     */
218
    @Override
219
    public EntityCache getCache() {
220
        if(((AbstractPopupEditor)getView()).isBeanLoaded()){
221
            return cache;
222
        } else {
223
            return null;
224
        }
225
    }
226

  
206 227

  
207 228
}

Also available in: Unified diff