Project

General

Profile

Download (7.06 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.vaadin.mvp;
10

    
11
import java.util.EnumSet;
12

    
13
import org.apache.log4j.Logger;
14
import org.hibernate.HibernateException;
15
import org.springframework.context.event.EventListener;
16

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

    
30
/**
31
 * Provides generic save operations of modified cdm entities.
32
 *
33
 * @author a.kohlbecker
34
 * @since Apr 5, 2017
35
 *
36
 */
37
public abstract class AbstractCdmEditorPresenter<DTO extends CdmBase, V extends ApplicationView<?>> extends AbstractEditorPresenter<DTO, V>
38
    implements CachingPresenter {
39

    
40
    private static final long serialVersionUID = 2218185546277084261L;
41

    
42
    private static final Logger logger = Logger.getLogger(AbstractCdmEditorPresenter.class);
43

    
44
    /**
45
     * if not null, this CRUD set is to be used to create a CdmAuthoritiy for the base entitiy which will be
46
     * granted to the current use as long this grant is not assigned yet.
47
     */
48
    protected EnumSet<CRUD> crud = null;
49

    
50

    
51
    private CdmEntityCache cache = null;
52

    
53
    public AbstractCdmEditorPresenter() {
54
        super();
55
        logger.trace(this._toString() + " constructor");
56
    }
57

    
58
    CdmStore<DTO, IService<DTO>> store ;
59

    
60
    protected CdmAuthority newAuthorityCreated;
61

    
62
    protected CdmStore<DTO, IService<DTO>> getStore() {
63
        if(store == null){
64
            store = new CdmStore<>(getRepo(), getService());
65
        }
66
        return store;
67
    }
68

    
69
    @Override
70
    protected DTO loadBeanById(Object identifier) {
71

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

    
86
        cache = new CdmEntityCache(cdmEntitiy);
87

    
88
        return cdmEntitiy;
89
    }
90

    
91

    
92
    /**
93
     * @param identifier
94
     * @return
95
     */
96
    protected abstract DTO loadCdmEntityById(Integer identifier);
97

    
98
    /**
99
     * Grant per entity CdmAuthority to the current user <b>for the bean which is not yet loaded</b>
100
     * into the editor. The <code>CRUD</code> to be granted are stored in the <code>crud</code> field.
101
     */
102
    protected abstract void guaranteePerEntityCRUDPermissions(Integer identifier);
103

    
104
    /**
105
     * Grant per entity CdmAuthority to the current user for the bean which is loaded
106
     * into the editor. The <code>CRUD</code> to be granted are stored in the <code>crud</code> field.
107
     */
108
     protected abstract void guaranteePerEntityCRUDPermissions(DTO bean);
109

    
110
    /**
111
     * @return
112
     */
113
    protected abstract IService<DTO> getService();
114

    
115
    @SuppressWarnings("unchecked")
116
    @Override
117
    @EventListener // the generic type parameter <DTO> must not be used here otherwise events will not be received
118
    public void onEditorPreSaveEvent(EditorPreSaveEvent preSaveEvent){
119

    
120
        if(!isFromOwnView(preSaveEvent)){
121
            return;
122
        }
123
        super.onEditorPreSaveEvent(preSaveEvent);
124
    }
125

    
126
    @SuppressWarnings("unchecked")
127
    @Override
128
    @EventListener // the generic type parameter <DTO> must not be used here otherwise events will not be received
129
    public void onEditorSaveEvent(EditorSaveEvent saveEvent){
130

    
131
        if(!isFromOwnView(saveEvent)){
132
            return;
133
        }
134

    
135

    
136
        // the bean is now updated with the changes made by the user
137
        DTO bean = (DTO) saveEvent.getBean();
138

    
139
        bean = handleTransientProperties(bean);
140
        try {
141
            EntityChangeEvent changeEvent = getStore().saveBean(bean);
142

    
143
            if(changeEvent != null){
144
                eventBus.publishEvent(changeEvent);
145
            }
146
        } catch (HibernateException e){
147
            if(newAuthorityCreated != null){
148
                UserHelper.fromSession().removeAuthorityForCurrentUser(newAuthorityCreated);
149
            }
150
        }
151
    }
152

    
153
    /**
154
     * EditorPresneters for beans with transient properties should overwrite this method to
155
     * update the beanItem with the changes made to the transient properties.
156
     * <p>
157
     * This is necessary because Vaadin MethodProperties are readonly when no setter is
158
     * available. This can be the case with transient properties. Automatic updating
159
     * of the property during the fieldGroup commit does not work in this case.
160
     *
161
     * @deprecated editors should operate on DTOs instead, remove this method if unused.
162
     */
163
    @Deprecated
164
    protected DTO handleTransientProperties(DTO bean) {
165
        // no need to handle transient properties in the generic case
166
        return bean;
167
    }
168

    
169
//    @Override
170
//    protected DTO prepareAsFieldGroupDataSource(DTO bean){
171
//        DTO mergedBean = getStore().mergedBean(bean);
172
//        // DTO mergedBean = bean;
173
//        return mergedBean;
174
//    }
175

    
176
    /**
177
     * If the bean is contained in the session it is being updated by
178
     * doing an evict and merge. The fieldGroup is updated with the merged bean.
179
     *
180
     * @param bean
181
     *
182
     * @return The bean merged to the session or original bean in case a merge was not necessary.
183
     */
184
    private DTO mergedBean(DTO bean) {
185
        DTO mergedBean = getStore().mergedBean(bean);
186
        ((AbstractPopupEditor<DTO, AbstractCdmEditorPresenter<DTO, V>>)getView()).updateItemDataSource(mergedBean);
187
        return mergedBean;
188

    
189
    }
190

    
191
    @Override
192
    protected
193
    final void saveBean(DTO bean){
194
        // blank implementation, since this is not needed in this or any sub class
195
        // see onEditorSaveEvent() instead
196
    }
197

    
198
    @Override
199
    protected final void deleteBean(DTO bean){
200
        EntityChangeEvent changeEvent = getStore().deleteBean(bean);
201
        if(changeEvent != null){
202
            eventBus.publishEvent(changeEvent);
203
        }
204

    
205
    }
206

    
207
    /**
208
     * @param crud
209
     */
210
    public void setGrantsForCurrentUser(EnumSet<CRUD> crud) {
211
        this.crud = crud;
212

    
213
    }
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

    
227

    
228
}
(1-1/8)