Project

General

Profile

Download (7.89 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

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

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

    
42
    private static final long serialVersionUID = 2218185546277084261L;
43

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

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

    
52

    
53
    private ICdmCacher cache;
54

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

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

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

    
64
    protected CdmAuthority newAuthorityCreated;
65

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

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

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

    
90

    
91
        cache = new CdmTransientEntityCacher(this);
92
        // need to use load but put see #7214
93
        cdmEntitiy = cache.load(cdmEntitiy);
94
        addRootEntity(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
    // @EventBusListenerMethod // already annotated at super class
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
    // @EventBusListenerMethod // already annotated at super class
137
    public void onEditorSaveEvent(EditorSaveEvent<DTO> saveEvent){
138

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

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

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

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

    
161
            if(changeEvent != null){
162
                viewEventBus.publish(this, changeEvent);
163
            }
164
        } catch (HibernateException e){
165
            if(newAuthorityCreated != null){
166
                UserHelper.fromSession().removeAuthorityForCurrentUser(newAuthorityCreated);
167
            }
168
            throw e;
169
        }
170
    }
171

    
172
    /**
173
     * EditorPresenters 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, (AbstractView) getView());
220
        if(changeEvent != null){
221
            viewEventBus.publish(this, 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)