Project

General

Profile

Download (8.01 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.ArrayList;
12
import java.util.Collection;
13
import java.util.EnumSet;
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 = new CdmTransientEntityCacher(this);
55

    
56
    private java.util.Collection<CdmBase> rootEntities = new ArrayList<>();
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
        cache.put(cdmEntitiy);
92
        rootEntities.add(cdmEntitiy);
93

    
94
        return cdmEntitiy;
95
    }
96

    
97

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

    
104
    /**
105
     * Grant per entity CdmAuthority to the current user <b>for the bean which is not yet loaded</b>
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(Integer identifier);
109

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

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

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

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

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

    
137
        if(!isFromOwnView(saveEvent)){
138
            return;
139
        }
140

    
141

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

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

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

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

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

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

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

    
206
    }
207

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

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

    
222
    }
223

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

    
230
    }
231

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

    
240

    
241

    
242
    /**
243
     * {@inheritDoc}
244
     */
245
    @Override
246
    public Collection<CdmBase> getRootEntities() {
247
        return rootEntities;
248
    }
249

    
250
    /**
251
     * Returns true only after the view method {@link AbstractPopupEditor#loadInEditor()}
252
     * has completed.
253
     *
254
     */
255
    @Override
256
    public boolean isCacheInitialized() {
257
        return ((AbstractPopupEditor)getView()).isBeanLoaded();
258
    }
259

    
260
}
(1-1/9)