Project

General

Profile

Download (7.81 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.debug.PersistentContextAnalyzer;
21
import eu.etaxonomy.cdm.model.common.CdmBase;
22
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
23
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;
24
import eu.etaxonomy.cdm.service.CdmStore;
25
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
26
import eu.etaxonomy.cdm.vaadin.security.UserHelper;
27
import eu.etaxonomy.cdm.vaadin.view.name.CachingPresenter;
28
import eu.etaxonomy.vaadin.mvp.event.EditorPreSaveEvent;
29
import eu.etaxonomy.vaadin.mvp.event.EditorSaveEvent;
30

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

    
41
    private static final long serialVersionUID = 2218185546277084261L;
42

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

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

    
51

    
52
    private CdmEntityCache cache = null;
53

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

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

    
61
    protected CdmAuthority newAuthorityCreated;
62

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

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

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

    
87
        cache = new CdmEntityCache(cdmEntitiy);
88

    
89
        return cdmEntitiy;
90
    }
91

    
92

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

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

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

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

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

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

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

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

    
136

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

    
140
        if(logger.isTraceEnabled()){
141
            PersistentContextAnalyzer pca = new PersistentContextAnalyzer(bean);
142
            pca.printEntityGraph(System.err);
143
            pca.printCopyEntities(System.err);
144
        }
145
        bean = handleTransientProperties(bean);
146

    
147
        if(logger.isTraceEnabled()){
148
            PersistentContextAnalyzer pca = new PersistentContextAnalyzer(bean);
149
            pca.printEntityGraph(System.err);
150
            pca.printCopyEntities(System.err);
151
        }
152
        try {
153
            EntityChangeEvent changeEvent = getStore().saveBean(bean);
154

    
155
            if(changeEvent != null){
156
                eventBus.publishEvent(changeEvent);
157
            }
158
        } catch (HibernateException e){
159
            if(newAuthorityCreated != null){
160
                UserHelper.fromSession().removeAuthorityForCurrentUser(newAuthorityCreated);
161
            }
162
        }
163
    }
164

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

    
181
//    @Override
182
//    protected DTO prepareAsFieldGroupDataSource(DTO bean){
183
//        DTO mergedBean = getStore().mergedBean(bean);
184
//        // DTO mergedBean = bean;
185
//        return mergedBean;
186
//    }
187

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

    
201
    }
202

    
203
    @Override
204
    protected
205
    final void saveBean(DTO bean){
206
        // blank implementation, since this is not needed in this or any sub class
207
        // see onEditorSaveEvent() instead
208
    }
209

    
210
    @Override
211
    protected final void deleteBean(DTO bean){
212
        EntityChangeEvent changeEvent = getStore().deleteBean(bean);
213
        if(changeEvent != null){
214
            eventBus.publishEvent(changeEvent);
215
        }
216

    
217
    }
218

    
219
    /**
220
     * @param crud
221
     */
222
    public void setGrantsForCurrentUser(EnumSet<CRUD> crud) {
223
        this.crud = crud;
224

    
225
    }
226

    
227
    /**
228
     * {@inheritDoc}
229
     */
230
    @Override
231
    public EntityCache getCache() {
232
        return cache;
233
//        if(((AbstractPopupEditor)getView()).isBeanLoaded()){
234
//        } else {
235
//            return null;
236
//        }
237
    }
238

    
239
    /**
240
     * Returns true only after the view method {@link AbstractPopupEditor#loadInEditor()}
241
     * has completed.
242
     *
243
     */
244
    @Override
245
    public boolean isCacheInitialized() {
246
        return ((AbstractPopupEditor)getView()).isBeanLoaded();
247
    }
248

    
249
}
(1-1/9)