Merge branch 'release/5.0.0'
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / ServiceBase.java
1 /**
2 * Copyright (C) 2007 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
10 package eu.etaxonomy.cdm.api.service;
11
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.UUID;
18
19 import org.apache.log4j.Logger;
20 import org.hibernate.LockOptions;
21 import org.hibernate.Session;
22 import org.springframework.context.ApplicationContext;
23 import org.springframework.context.ApplicationContextAware;
24 import org.springframework.dao.DataAccessException;
25 import org.springframework.transaction.annotation.Transactional;
26
27 import eu.etaxonomy.cdm.api.service.pager.Pager;
28 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
29 import eu.etaxonomy.cdm.model.common.CdmBase;
30 import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
31 import eu.etaxonomy.cdm.persistence.dto.MergeResult;
32 import eu.etaxonomy.cdm.persistence.query.Grouping;
33 import eu.etaxonomy.cdm.persistence.query.OrderHint;
34
35 public abstract class ServiceBase<T extends CdmBase, DAO extends ICdmEntityDao<T>> implements IService<T>, ApplicationContextAware {
36 @SuppressWarnings("unused")
37 private static final Logger logger = Logger.getLogger(ServiceBase.class);
38
39 //flush after saving this number of objects
40 int flushAfterNo = 2000;
41 protected ApplicationContext appContext;
42
43 protected DAO dao;
44
45 @Override
46 @Transactional(readOnly = true)
47 public void lock(T t, LockOptions lockOptions) {
48 dao.lock(t, lockOptions);
49 }
50
51 @Override
52 @Transactional(readOnly = true)
53 public void refresh(T t, LockOptions lockOptions, List<String> propertyPaths) {
54 dao.refresh(t, lockOptions, propertyPaths);
55 }
56
57 @Override
58 @Transactional(readOnly = false)
59 public void clear() {
60 dao.clear();
61 }
62
63 @Override
64 @Transactional(readOnly = true)
65 public int count(Class<? extends T> clazz) {
66 return dao.count(clazz);
67 }
68
69 @Override
70 @Transactional(readOnly = false)
71 public DeleteResult delete(UUID persistentObjectUUID) {
72 T persistentObject = dao.findByUuid(persistentObjectUUID);
73 return delete(persistentObject);
74 }
75
76 @Override
77 @Transactional(readOnly = false)
78 public DeleteResult delete(Collection<UUID> persistentObjectUUIDs) {
79 DeleteResult result = new DeleteResult();
80 for(UUID persistentObjectUUID : persistentObjectUUIDs) {
81 T persistentObject = dao.findByUuid(persistentObjectUUID);
82 DeleteResult dr = delete(persistentObject);
83 result.includeResult(dr);
84 }
85 return result;
86 }
87
88 @Override
89 @Transactional(readOnly = false)
90 public DeleteResult delete(T persistentObject) {
91 DeleteResult result = new DeleteResult();
92 try{
93 dao.delete(persistentObject);
94 result.addDeletedObject(persistentObject);
95 } catch(DataAccessException e){
96 result.setError();
97 result.addException(e);
98 }
99 return result;
100 }
101
102
103
104 @Override
105 @Transactional(readOnly = true)
106 public boolean exists(UUID uuid) {
107 return dao.exists(uuid);
108 }
109
110 @Override
111 @Transactional(readOnly = true)
112 public List<T> find(Set<UUID> uuidSet) {
113 return dao.list(uuidSet, null, null, null, null);
114 }
115
116 @Override
117 @Transactional(readOnly = true)
118 public List<T> findById(Set<Integer> idSet) { //can't be called find(Set<Integer>) as this conflicts with find(Set<UUID)
119 return dao.loadList(idSet, null);
120 }
121
122 @Override
123 @Transactional(readOnly = true)
124 public List<T> loadByIds(List<Integer> idList, List<String> propertyPaths){
125 return dao.loadList(idList, propertyPaths);
126 }
127
128 @Override
129 @Transactional(readOnly = true)
130 public T find(UUID uuid) {
131 return uuid == null ? null : dao.findByUuid(uuid);
132 }
133
134 @Override
135 @Transactional(readOnly = true)
136 public T findWithoutFlush(UUID uuid) {
137 return uuid == null ? null : dao.findByUuidWithoutFlush(uuid);
138 }
139
140 @Override
141 @Transactional(readOnly = true)
142 public T find(int id) {
143 return dao.findById(id);
144 }
145
146 @Override
147 @Transactional(readOnly = true)
148 public Session getSession() {
149 return dao.getSession();
150 }
151
152 @Override
153 @Transactional(readOnly = true)
154 public List<Object[]> group(Class<? extends T> clazz,Integer limit, Integer start, List<Grouping> groups, List<String> propertyPaths) {
155 return dao.group(clazz, limit, start, groups, propertyPaths);
156 }
157
158 @Override
159 @Transactional(readOnly = true)
160 public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths){
161 return dao.list(type,limit, start, orderHints, propertyPaths);
162 }
163
164 @Override
165 @Transactional(readOnly = true)
166 public T load(UUID uuid) {
167 return uuid == null ? null : dao.load(uuid);
168 }
169
170 @Override
171 @Transactional(readOnly = true)
172 public T loadWithUpdate(UUID uuid) {
173 return load(uuid);
174 }
175
176 @Override
177 @Transactional(readOnly = true)
178 public T load(int id, List<String> propertyPaths) {
179 return dao.load(id, propertyPaths);
180 }
181
182 @Override
183 @Transactional(readOnly = true)
184 public T load(UUID uuid, List<String> propertyPaths){
185 return uuid == null ? null : dao.load(uuid, propertyPaths);
186 }
187
188 @Override
189 @Transactional(readOnly = true)
190 public List<T> load(List<UUID> uuids, List<String> propertyPaths){
191 if(uuids == null) {
192 return null;
193 }
194
195 List<T> entities = new ArrayList<T>();
196 for(UUID uuid : uuids) {
197 entities.add(uuid == null ? null : dao.load(uuid, propertyPaths));
198 }
199 return entities;
200 }
201
202 @Override
203 @Transactional(readOnly = false)
204 public T merge(T newInstance) {
205 return dao.merge(newInstance);
206 }
207
208 @Override
209 @Transactional(readOnly = false)
210 public MergeResult<T> merge(T newInstance, boolean returnTransientEntity) {
211 return dao.merge(newInstance, returnTransientEntity);
212 }
213
214 @Override
215 @Transactional(readOnly = false)
216 public List<T> merge(List<T> detachedObjects) {
217 List<T> mergedObjects = new ArrayList<T>();
218 for(T obj : detachedObjects) {
219 mergedObjects.add(dao.merge(obj));
220 }
221 return mergedObjects;
222 }
223
224 @Override
225 @Transactional(readOnly = false)
226 public List<MergeResult<T>> merge(List<T> detachedObjects, boolean returnTransientEntity) {
227 List<MergeResult<T>> mergedObjects = new ArrayList<MergeResult<T>>();
228 for(T obj : detachedObjects) {
229 mergedObjects.add(dao.merge(obj, returnTransientEntity));
230 }
231 return mergedObjects;
232 }
233
234 @Override
235 @Transactional(readOnly = true)
236 public <S extends T> Pager<S> page(Class<S> type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
237 Integer numberOfResults = dao.count(type);
238 List<S> results = new ArrayList<S>();
239 pageNumber = pageNumber == null ? 0 : pageNumber;
240 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
241 Integer start = pageSize == null ? 0 : pageSize * pageNumber;
242 results = dao.list(type, pageSize, start, orderHints,propertyPaths);
243 }
244 return new DefaultPagerImpl<S>(pageNumber, numberOfResults, pageSize, results);
245 }
246
247 @Override
248 @Transactional(readOnly = true)
249 public UUID refresh(T persistentObject) {
250 return dao.refresh(persistentObject);
251 }
252
253 /**
254 * FIXME Candidate for harmonization
255 * is this method used, and if so, should it be exposed in the service layer?
256 * it seems a bit incongruous that we use an ORM to hide the fact that there is a
257 * database, then expose a method that talks about "rows" . . .
258 */
259 @Override
260 @Transactional(readOnly = true)
261 public List<T> rows(String tableName, int limit, int start) {
262 return dao.rows(tableName, limit, start);
263 }
264
265 @Override
266 @Transactional(readOnly = false)
267 public Map<UUID, T> save(Collection<T> newInstances) {
268 return dao.saveAll(newInstances);
269 }
270
271 @Override
272 @Transactional(readOnly = false)
273 public T save(T newInstance) {
274 return dao.save(newInstance);
275 }
276
277 @Override
278 @Transactional(readOnly = false)
279 public UUID saveOrUpdate(T transientObject) {
280 return dao.saveOrUpdate(transientObject);
281 }
282
283 @Override
284 @Transactional(readOnly = false)
285 public Map<UUID, T> saveOrUpdate(Collection<T> transientInstances) {
286 return dao.saveOrUpdateAll(transientInstances);
287 }
288
289 @Override
290 public void setApplicationContext(ApplicationContext appContext){
291 this.appContext = appContext;
292 }
293
294
295 protected abstract void setDao(DAO dao);
296
297 @Override
298 @Transactional(readOnly = false)
299 public UUID update(T transientObject) {
300 return dao.update(transientObject);
301 }
302
303 @Override
304 @Transactional(readOnly = true)
305 public List<T> list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
306 return dao.list(example, includeProperties, limit, start, orderHints, propertyPaths);
307 }
308
309
310
311 }