Project

General

Profile

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

    
11
import java.util.Collection;
12
import java.util.EnumSet;
13
import java.util.HashSet;
14

    
15
import org.apache.log4j.Logger;
16
import org.hibernate.HibernateException;
17
import org.springframework.context.event.EventListener;
18

    
19
import eu.etaxonomy.cdm.api.service.IService;
20
import eu.etaxonomy.cdm.cache.CdmTransientEntityCacher;
21
import eu.etaxonomy.cdm.debug.PersistentContextAnalyzer;
22
import eu.etaxonomy.cdm.model.ICdmCacher;
23
import eu.etaxonomy.cdm.model.common.CdmBase;
24
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
25
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;
26
import eu.etaxonomy.cdm.service.CdmStore;
27
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
28
import eu.etaxonomy.cdm.vaadin.security.UserHelper;
29
import eu.etaxonomy.cdm.vaadin.view.name.CachingPresenter;
30
import eu.etaxonomy.vaadin.mvp.event.EditorPreSaveEvent;
31
import eu.etaxonomy.vaadin.mvp.event.EditorSaveEvent;
32

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

    
43
    private static final long serialVersionUID = 2218185546277084261L;
44

    
45
    private static final Logger logger = Logger.getLogger(AbstractCdmEditorPresenter.class);
46

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

    
53

    
54
    private ICdmCacher cache;
55

    
56
    private java.util.Collection<CdmBase> rootEntities = new HashSet<>();
57

    
58
    public AbstractCdmEditorPresenter() {
59
        super();
60
        logger.trace(this._toString() + " constructor");
61
    }
62

    
63
    CdmStore<DTO, IService<DTO>> store ;
64

    
65
    protected CdmAuthority newAuthorityCreated;
66

    
67
    protected CdmStore<DTO, IService<DTO>> getStore() {
68
        if(store == null){
69
            store = new CdmStore<>(getRepo(), getService());
70
        }
71
        return store;
72
    }
73

    
74
    @Override
75
    protected DTO loadBeanById(Object identifier) {
76

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

    
91

    
92
        cache = new CdmTransientEntityCacher(this);
93
        cache.put(cdmEntitiy);
94
        rootEntities.add(cdmEntitiy);
95

    
96
        return cdmEntitiy;
97
    }
98

    
99

    
100
    /**
101
     * @param identifier
102
     * @return
103
     */
104
    protected abstract DTO loadCdmEntityById(Integer identifier);
105

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

    
112
    /**
113
     * Grant per entity CdmAuthority to the current user for the bean which is loaded
114
     * into the editor. The <code>CRUD</code> to be granted are stored in the <code>crud</code> field.
115
     */
116
     protected abstract void guaranteePerEntityCRUDPermissions(DTO bean);
117

    
118
    /**
119
     * @return
120
     */
121
    protected abstract IService<DTO> getService();
122

    
123
    @SuppressWarnings("unchecked")
124
    @Override
125
    @EventListener // the generic type parameter <DTO> must not be used here otherwise events will not be received
126
    public void onEditorPreSaveEvent(EditorPreSaveEvent preSaveEvent){
127

    
128
        if(!isFromOwnView(preSaveEvent)){
129
            return;
130
        }
131
        super.onEditorPreSaveEvent(preSaveEvent);
132
    }
133

    
134
    @SuppressWarnings("unchecked")
135
    @Override
136
    @EventListener // the generic type parameter <DTO> must not be used here otherwise events will not be received
137
    public void onEditorSaveEvent(EditorSaveEvent saveEvent){
138

    
139
        if(!isFromOwnView(saveEvent)){
140
            return;
141
        }
142

    
143

    
144
        // the bean is now updated with the changes made by the user
145
        DTO bean = (DTO) saveEvent.getBean();
146

    
147
        if(logger.isTraceEnabled()){
148
            PersistentContextAnalyzer pca = new PersistentContextAnalyzer(bean);
149
            pca.printEntityGraph(System.err);
150
            pca.printCopyEntities(System.err);
151
        }
152
        bean = handleTransientProperties(bean);
153

    
154
        if(logger.isTraceEnabled()){
155
            PersistentContextAnalyzer pca = new PersistentContextAnalyzer(bean);
156
            pca.printEntityGraph(System.err);
157
            pca.printCopyEntities(System.err);
158
        }
159
        try {
160
            EntityChangeEvent changeEvent = getStore().saveBean(bean);
161

    
162
            if(changeEvent != null){
163
                eventBus.publishEvent(changeEvent);
164
            }
165
        } catch (HibernateException e){
166
            if(newAuthorityCreated != null){
167
                UserHelper.fromSession().removeAuthorityForCurrentUser(newAuthorityCreated);
168
            }
169
        }
170
    }
171

    
172
    /**
173
     * EditorPresneters for beans with transient properties should overwrite this method to
174
     * update the beanItem with the changes made to the transient properties.
175
     * <p>
176
     * This is necessary because Vaadin MethodProperties are readonly when no setter is
177
     * available. This can be the case with transient properties. Automatic updating
178
     * of the property during the fieldGroup commit does not work in this case.
179
     *
180
     * @deprecated editors should operate on DTOs instead, remove this method if unused.
181
     */
182
    @Deprecated
183
    protected DTO handleTransientProperties(DTO bean) {
184
        // no need to handle transient properties in the generic case
185
        return bean;
186
    }
187

    
188
//    @Override
189
//    protected DTO prepareAsFieldGroupDataSource(DTO bean){
190
//        DTO mergedBean = getStore().mergedBean(bean);
191
//        // DTO mergedBean = bean;
192
//        return mergedBean;
193
//    }
194

    
195
    /**
196
     * If the bean is contained in the session it is being updated by
197
     * doing an evict and merge. The fieldGroup is updated with the merged bean.
198
     *
199
     * @param bean
200
     *
201
     * @return The bean merged to the session or original bean in case a merge was not necessary.
202
     */
203
    private DTO mergedBean(DTO bean) {
204
        DTO mergedBean = getStore().mergedBean(bean);
205
        ((AbstractPopupEditor<DTO, AbstractCdmEditorPresenter<DTO, V>>)getView()).updateItemDataSource(mergedBean);
206
        return mergedBean;
207

    
208
    }
209

    
210
    @Override
211
    protected
212
    final void saveBean(DTO bean){
213
        // blank implementation, since this is not needed in this or any sub class
214
        // see onEditorSaveEvent() instead
215
    }
216

    
217
    @Override
218
    protected final void deleteBean(DTO bean){
219
        EntityChangeEvent changeEvent = getStore().deleteBean(bean);
220
        if(changeEvent != null){
221
            eventBus.publishEvent(changeEvent);
222
        }
223

    
224
    }
225

    
226
    /**
227
     * @param crud
228
     */
229
    public void setGrantsForCurrentUser(EnumSet<CRUD> crud) {
230
        this.crud = crud;
231

    
232
    }
233

    
234
    /**
235
     * {@inheritDoc}
236
     */
237
    @Override
238
    public ICdmCacher getCache() {
239
        return cache;
240
    }
241

    
242
    /**
243
     * {@inheritDoc}
244
     */
245
    @Override
246
    public void addRootEntity(CdmBase entity) {
247
        rootEntities.add(entity);
248
    }
249

    
250

    
251
    /**
252
     * {@inheritDoc}
253
     */
254
    @Override
255
    public Collection<CdmBase> getRootEntities() {
256
        return rootEntities;
257
    }
258

    
259

    
260
}
(1-1/9)