Project

General

Profile

Download (7.85 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.cdm.service;
10

    
11
import org.apache.log4j.Logger;
12
import org.hibernate.Session;
13
import org.springframework.beans.factory.annotation.Autowired;
14
import org.springframework.beans.factory.annotation.Qualifier;
15
import org.springframework.transaction.TransactionStatus;
16

    
17
import com.vaadin.spring.annotation.SpringComponent;
18
import com.vaadin.spring.annotation.ViewScope;
19
import com.vaadin.ui.Notification;
20
import com.vaadin.ui.UI;
21

    
22
import eu.etaxonomy.cdm.api.application.CdmRepository;
23
import eu.etaxonomy.cdm.api.service.DeleteResult;
24
import eu.etaxonomy.cdm.api.service.IService;
25
import eu.etaxonomy.cdm.model.agent.AgentBase;
26
import eu.etaxonomy.cdm.model.common.CdmBase;
27
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
28
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
29
import eu.etaxonomy.cdm.model.name.Registration;
30
import eu.etaxonomy.cdm.model.name.TaxonName;
31
import eu.etaxonomy.cdm.model.occurrence.Collection;
32
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
33
import eu.etaxonomy.cdm.model.reference.Reference;
34
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
35
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent.Type;
36
import eu.etaxonomy.vaadin.mvp.AbstractView;
37

    
38
/**
39
 * @author a.kohlbecker
40
 * @since Jun 26, 2017
41
 *
42
 * TODO better naming of this class, ServiceWrapper, ServiceOperator, ...?
43
 *
44
 */
45
@SpringComponent
46
@ViewScope
47
public class CdmStore {
48

    
49
    private static final Logger logger = Logger.getLogger(CdmStore.class);
50

    
51
    @Autowired
52
    @Qualifier("cdmRepository")
53
    private CdmRepository repo;
54

    
55

    
56
    /**
57
     * If the bean is contained in the session it is being updated by doing an
58
     * evict and merge. The fieldGroup is updated with the merged bean.
59
     *
60
     *
61
     * @param bean
62
     * @return The bean merged to the session or original bean in case a merge
63
     *         was not necessary.
64
     */
65
    public <T extends CdmBase> T mergedBean(T bean) throws IllegalStateException {
66

    
67
        TransactionStatus txStatus = repo.startTransaction();
68
        Session session = repo.getSession();
69

    
70
        if (session.contains(bean)) {
71
            // evict bean before merge to avoid duplicate beans in same session
72
            logger.trace(this._toString() + ".mergedBean() - evict " + bean.toString());
73
            session.evict(bean);
74
        }
75

    
76
        logger.trace(this._toString() + ".mergedBean() - doing merge of" + bean.toString());
77
        @SuppressWarnings("unchecked")
78
        T mergedBean = (T) session.merge(bean);
79
        session.flush();
80
        repo.commitTransaction(txStatus);
81
        logger.trace(this._toString() + ".mergedBean() - bean after merge " + bean.toString());
82
        return mergedBean;
83

    
84
    }
85

    
86

    
87
    protected String _toString() {
88
        return this.getClass().getSimpleName() + "@" + this.hashCode();
89
    }
90

    
91
    /**
92
     *
93
     * @param bean
94
     *
95
     * @return the merged bean, this bean is <b>not reloaded</b> from the
96
     *         persistent storage.
97
     */
98
    public <T extends CdmBase> EntityChangeEvent saveBean(T bean, AbstractView view) {
99

    
100
        Type changeEventType;
101
        if(bean.isPersited()){
102
            changeEventType = Type.MODIFIED;
103
        } else {
104
            changeEventType = Type.CREATED;
105
        }
106

    
107
        TransactionStatus txStatus = repo.startTransaction();
108
        Session session = repo.getSession();
109
        logger.trace(this._toString() + ".onEditorSaveEvent - merging bean into session");
110
        // merge the changes into the session, ...
111
        T mergedBean = mergedBean(bean);
112
        session.flush();
113
        repo.commitTransaction(txStatus);
114
        return new EntityChangeEvent(mergedBean, changeEventType, view);
115

    
116
                repo.getTransactionManager().rollback(txStatus);
117
                throw e;
118
            }
119
    }
120

    
121
    /**
122
     *
123
     * @param bean
124
     * @return a EntityChangeEvent in case the deletion was successful otherwise <code>null</code>.
125
     */
126
    public final <T extends CdmBase> EntityChangeEvent deleteBean(T bean, AbstractView view) {
127

    
128
        IService<T> typeSpecificService = serviceFor(bean);
129

    
130
        logger.trace(this._toString() + ".onEditorPreSaveEvent - starting transaction");
131
        TransactionStatus txStatus = repo.startTransaction();
132
        Session session = repo.getSession();
133
        logger.trace(this._toString() + ".deleteBean - deleting" + bean.toString());
134
        DeleteResult result = typeSpecificService.delete(bean);
135
        if (result.isOk()) {
136
            session.flush();
137
            repo.commitTransaction(txStatus);
138
            logger.trace(this._toString() + ".deleteBean - transaction comitted");
139
            return new EntityChangeEvent(bean, Type.REMOVED, view);
140
        } else {
141
            handleDeleteresultInError(result);
142
        }
143

    
144
        return null;
145
    }
146

    
147
    /**
148
     * @param result
149
     */
150
    public static void handleDeleteresultInError(DeleteResult result) {
151
        String notificationTitle;
152
        StringBuffer messageBody = new StringBuffer();
153
        if (result.isAbort()) {
154
            notificationTitle = "The delete operation as abborded by the system.";
155
        } else {
156
            notificationTitle = "An error occured during the delete operation.";
157
        }
158
        if (!result.getExceptions().isEmpty()) {
159
            messageBody.append("<h3>").append("Exceptions:").append("</h3>").append("<ul>");
160
            result.getExceptions().forEach(e -> messageBody.append("<li>").append(e.getMessage()).append("</li>"));
161
            messageBody.append("</ul>");
162
        }
163
        if (!result.getRelatedObjects().isEmpty()) {
164
            messageBody.append("<h3>").append("Related objects exist:").append("</h3>").append("<ul>");
165
            result.getRelatedObjects().forEach(e -> {
166
                messageBody.append("<li>");
167
                if (IdentifiableEntity.class.isAssignableFrom(e.getClass())) {
168
                    messageBody.append(((IdentifiableEntity) e).getTitleCache());
169
                } else {
170
                    messageBody.append(e.toString());
171
                }
172
                messageBody.append("</li>");
173
            });
174

    
175
            messageBody.append("</ul>");
176
        }
177
        Notification notification = new Notification(notificationTitle, messageBody.toString(),
178
                com.vaadin.ui.Notification.Type.ERROR_MESSAGE, true);
179
        notification.show(UI.getCurrent().getPage());
180
    }
181

    
182
    @SuppressWarnings("unchecked")
183
    protected <T extends CdmBase> IService<T> serviceFor(T bean){
184
         Class<? extends CdmBase> cdmType = bean.getClass();
185
         if(Registration.class.isAssignableFrom(cdmType)){
186
             return (IService<T>) repo.getRegistrationService();
187
         } else if(TaxonName.class.isAssignableFrom(cdmType)){
188
             return (IService<T>) repo.getNameService();
189
         } else if(Reference.class.isAssignableFrom(cdmType)){
190
             return (IService<T>) repo.getReferenceService();
191
         } else if (NameTypeDesignation.class.isAssignableFrom(cdmType)){
192
             throw new RuntimeException("no generic sercvice for NameTypeDesignation, use dedicated methods of NameService");
193
         } else if (SpecimenOrObservationBase.class.isAssignableFrom(cdmType)){
194
             return (IService<T>) repo.getOccurrenceService();
195
         } else if (AgentBase.class.isAssignableFrom(cdmType)){
196
             return (IService<T>) repo.getAgentService();
197
         } else if (Collection.class.isAssignableFrom(cdmType)){
198
             return (IService<T>) repo.getCollectionService();
199
         } else if (Collection.class.isAssignableFrom(cdmType)){
200
             return (IService<T>) repo.getCollectionService();
201
         } else {
202
             throw new RuntimeException("Implementation to find service for " + cdmType + " still missing.");
203
         }
204
    }
205

    
206
}
(4-4/10)