Merge branch 'develop' of ssh://dev.e-taxonomy.eu/var/git/cdmlib into develop
[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.hibernate.criterion.Criterion;
23 import org.springframework.context.ApplicationContext;
24 import org.springframework.context.ApplicationContextAware;
25 import org.springframework.dao.DataAccessException;
26 import org.springframework.transaction.annotation.Transactional;
27
28 import eu.etaxonomy.cdm.api.service.pager.Pager;
29 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
30 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
31 import eu.etaxonomy.cdm.exception.UnpublishedException;
32 import eu.etaxonomy.cdm.model.common.CdmBase;
33 import eu.etaxonomy.cdm.model.common.IPublishable;
34 import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
35 import eu.etaxonomy.cdm.persistence.dao.common.Restriction;
36 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.DaoBase;
37 import eu.etaxonomy.cdm.persistence.dto.MergeResult;
38 import eu.etaxonomy.cdm.persistence.query.Grouping;
39 import eu.etaxonomy.cdm.persistence.query.MatchMode;
40 import eu.etaxonomy.cdm.persistence.query.OrderHint;
41
42 public abstract class ServiceBase<T extends CdmBase, DAO extends ICdmEntityDao<T>>
43 implements IService<T>, ApplicationContextAware {
44
45 @SuppressWarnings("unused")
46 private static final Logger logger = Logger.getLogger(ServiceBase.class);
47
48 protected ApplicationContext appContext;
49
50 public final static boolean NO_UNPUBLISHED = DaoBase.NO_UNPUBLISHED; //constant for unpublished
51 public final static boolean INCLUDE_UNPUBLISHED = DaoBase.INCLUDE_UNPUBLISHED; //constant for unpublished
52
53 protected DAO dao;
54
55 @Override
56 @Transactional(readOnly = true)
57 public void lock(T t, LockOptions lockOptions) {
58 dao.lock(t, lockOptions);
59 }
60
61 @Override
62 @Transactional(readOnly = true)
63 public void refresh(T t, LockOptions lockOptions, List<String> propertyPaths) {
64 dao.refresh(t, lockOptions, propertyPaths);
65 }
66
67 @Override
68 @Transactional(readOnly = false)
69 public void clear() {
70 dao.clear();
71 }
72
73 @Override
74 @Transactional(readOnly = true)
75 public int count(Class<? extends T> clazz) {
76 return Long.valueOf(dao.count(clazz)).intValue();
77 }
78
79 @Override
80 @Transactional(readOnly = false)
81 public DeleteResult delete(UUID persistentObjectUUID) {
82 T persistentObject = dao.findByUuid(persistentObjectUUID);
83 return delete(persistentObject);
84 }
85
86 @Override
87 @Transactional(readOnly = false)
88 public DeleteResult delete(Collection<UUID> persistentObjectUUIDs) {
89 DeleteResult result = new DeleteResult();
90 for(UUID persistentObjectUUID : persistentObjectUUIDs) {
91 T persistentObject = dao.findByUuid(persistentObjectUUID);
92 DeleteResult dr = delete(persistentObject);
93 result.includeResult(dr);
94 }
95 return result;
96 }
97
98 @Override
99 @Transactional(readOnly = false)
100 public DeleteResult delete(T persistentObject) {
101 DeleteResult result = new DeleteResult();
102 try{
103 dao.delete(persistentObject);
104 result.addDeletedObject(persistentObject);
105 } catch(DataAccessException e){
106 result.setError();
107 result.addException(e);
108 }
109 return result;
110 }
111
112
113
114 @Override
115 @Transactional(readOnly = true)
116 public boolean exists(UUID uuid) {
117 return dao.exists(uuid);
118 }
119
120 @Override
121 @Transactional(readOnly = true)
122 public List<T> find(Set<UUID> uuidSet) {
123 return dao.list(uuidSet, null, null, null, null);
124 }
125
126
127 @Override
128 @Transactional(readOnly = true)
129 public <S extends T> List<S> find(Class<S> clazz, Set<UUID> uuidSet) {
130 return dao.list(clazz, uuidSet, null, null, null, null);
131 }
132
133 @Override
134 @Transactional(readOnly = true)
135 public List<T> findById(Set<Integer> idSet) { //can't be called find(Set<Integer>) as this conflicts with find(Set<UUID)
136 return dao.loadList(idSet, null, null);
137 }
138
139 @Override
140 @Transactional(readOnly = true)
141 public List<T> loadByIds(List<Integer> idList, List<String> propertyPaths){
142 return dao.loadList(idList, null, propertyPaths);
143 }
144
145 @Override
146 @Transactional(readOnly = true)
147 public List<T> loadByIds(List<Integer> idList, List<OrderHint> orderHints, List<String> propertyPaths){
148 return dao.loadList(idList, orderHints, propertyPaths);
149 }
150
151 @Override
152 @Transactional(readOnly = true)
153 public T find(UUID uuid) {
154 return uuid == null ? null : dao.findByUuid(uuid);
155 }
156
157 @Override
158 @Transactional(readOnly = true)
159 public T findWithoutFlush(UUID uuid) {
160 return uuid == null ? null : dao.findByUuidWithoutFlush(uuid);
161 }
162
163 @Override
164 @Transactional(readOnly = true)
165 public T find(int id) {
166 return dao.findById(id);
167 }
168
169 @Override
170 @Transactional(readOnly = true)
171 public Session getSession() {
172 return dao.getSession();
173 }
174
175 @Override
176 @Transactional(readOnly = true)
177 public List<Object[]> group(Class<? extends T> clazz,Integer limit, Integer start, List<Grouping> groups, List<String> propertyPaths) {
178 return dao.group(clazz, limit, start, groups, propertyPaths);
179 }
180
181 @Override
182 @Transactional(readOnly = true)
183 public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths){
184 return dao.list(type,limit, start, orderHints, propertyPaths);
185 }
186
187 @Override
188 @Transactional(readOnly = true)
189 public T load(UUID uuid) {
190 return uuid == null ? null : dao.load(uuid);
191 }
192
193 @Override
194 @Transactional(readOnly = true)
195 public T loadWithUpdate(UUID uuid) {
196 return load(uuid);
197 }
198
199 @Override
200 @Transactional(readOnly = true)
201 public T load(int id, List<String> propertyPaths) {
202 return dao.load(id, propertyPaths);
203 }
204
205 @Override
206 @Transactional(readOnly = true)
207 public T load(UUID uuid, List<String> propertyPaths){
208 return uuid == null ? null : dao.load(uuid, propertyPaths);
209 }
210
211 @Override
212 @Transactional(readOnly = true)
213 public List<T> load(List<UUID> uuids, List<String> propertyPaths){
214 if(uuids == null) {
215 return null;
216 }
217
218 List<T> entities = new ArrayList<>();
219 for(UUID uuid : uuids) {
220 entities.add(uuid == null ? null : dao.load(uuid, propertyPaths));
221 }
222 return entities;
223 }
224
225 @Override
226 @Transactional(readOnly = false)
227 public T merge(T newInstance) {
228 return dao.merge(newInstance);
229 }
230
231 @Override
232 @Transactional(readOnly = false)
233 public MergeResult<T> merge(T newInstance, boolean returnTransientEntity) {
234 return dao.merge(newInstance, returnTransientEntity);
235 }
236
237 @Override
238 @Transactional(readOnly = false)
239 public List<T> merge(List<T> detachedObjects) {
240 List<T> mergedObjects = new ArrayList<T>();
241 for(T obj : detachedObjects) {
242 mergedObjects.add(dao.merge(obj));
243 }
244 return mergedObjects;
245 }
246
247 @Override
248 @Transactional(readOnly = false)
249 public List<MergeResult<T>> merge(List<T> detachedObjects, boolean returnTransientEntity) {
250 List<MergeResult<T>> mergedObjects = new ArrayList<MergeResult<T>>();
251 for(T obj : detachedObjects) {
252 mergedObjects.add(dao.merge(obj, returnTransientEntity));
253 }
254 return mergedObjects;
255 }
256
257 @Override
258 @Transactional(readOnly = true)
259 public <S extends T> Pager<S> page(Class<S> type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
260 Long numberOfResults = dao.count(type);
261 List<S> results = new ArrayList<>();
262 pageNumber = pageNumber == null ? 0 : pageNumber;
263 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
264 Integer start = pageSize == null ? 0 : pageSize * pageNumber;
265 results = dao.list(type, pageSize, start, orderHints, propertyPaths);
266 }
267 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
268 }
269
270 @Override
271 @Transactional(readOnly = true)
272 public UUID refresh(T persistentObject) {
273 return dao.refresh(persistentObject);
274 }
275
276 @Override
277 @Transactional(readOnly = false)
278 public Map<UUID, T> save(Collection<T> newInstances) {
279 return dao.saveAll(newInstances);
280 }
281
282 @Override
283 @Transactional(readOnly = false)
284 public T save(T newInstance) {
285 return dao.save(newInstance);
286 }
287
288 @Override
289 @Transactional(readOnly = false)
290 public UUID saveOrUpdate(T transientObject) {
291 return dao.saveOrUpdate(transientObject);
292 }
293
294 @Override
295 @Transactional(readOnly = false)
296 public Map<UUID, T> saveOrUpdate(Collection<T> transientInstances) {
297 return dao.saveOrUpdateAll(transientInstances);
298 }
299
300 @Override
301 public void setApplicationContext(ApplicationContext appContext){
302 this.appContext = appContext;
303 }
304
305
306 protected abstract void setDao(DAO dao);
307
308 @Override
309 @Transactional(readOnly = false)
310 public UUID update(T transientObject) {
311 return dao.update(transientObject);
312 }
313
314 @Override
315 @Transactional(readOnly = true)
316 public List<T> list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
317 return dao.list(example, includeProperties, limit, start, orderHints, propertyPaths);
318 }
319
320 @Override
321 @Transactional(readOnly = true)
322 public <S extends T> Pager<S> page(Class<S> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths){
323
324 List<S> records;
325 long resultSize = dao.countByParam(clazz, param, queryString, matchmode, criteria);
326 if(AbstractPagerImpl.hasResultsInRange(resultSize, pageIndex, pageSize)){
327 records = dao.findByParam(clazz, param, queryString, matchmode, criteria, pageSize, pageIndex, orderHints, propertyPaths);
328 } else {
329 records = new ArrayList<>();
330 }
331 return new DefaultPagerImpl<>(pageIndex, resultSize, pageSize, records);
332 }
333
334
335 @Override
336 @Transactional(readOnly = true)
337 public <S extends T> Pager<S> pageByParamWithRestrictions(Class<S> clazz, String param, String queryString, MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths){
338
339 List<S> records;
340 long resultSize = dao.countByParamWithRestrictions(clazz, param, queryString, matchmode, restrictions);
341 if(AbstractPagerImpl.hasResultsInRange(resultSize, pageIndex, pageSize)){
342 records = dao.findByParamWithRestrictions(clazz, param, queryString, matchmode, restrictions, pageSize, pageIndex, orderHints, propertyPaths);
343 } else {
344 records = new ArrayList<>();
345 }
346 Pager<S> pager = new DefaultPagerImpl<>(pageIndex, resultSize, pageSize, records);
347 return pager;
348 }
349
350 @Override
351 @Transactional(readOnly = true)
352 public <S extends T> Pager<S> page(Class<S> clazz, List<Restriction<?>> restrictions, Integer pageSize, Integer pageIndex, List<OrderHint> orderHints, List<String> propertyPaths){
353
354 List<S> records;
355 long resultSize = dao.count(clazz, restrictions);
356 if(AbstractPagerImpl.hasResultsInRange(resultSize, pageIndex, pageSize)){
357 records = dao.list(clazz, restrictions, pageSize, pageIndex, orderHints, propertyPaths);
358 } else {
359 records = new ArrayList<>();
360 }
361 Pager<S> pager = new DefaultPagerImpl<>(pageIndex, resultSize, pageSize, records);
362 return pager;
363 }
364
365
366 /**
367 * Throws an exception if the publishable entity should not be published.
368 * @param publishable the publishable entity
369 * @param includeUnpublished should publish be checked
370 * @param message the error message to include
371 * @throws UnpublishedException thrown if entity is not public and unpublished should not be included
372 */
373 protected void checkPublished(IPublishable publishable, boolean includeUnpublished, String message) throws UnpublishedException {
374 if (!(includeUnpublished || publishable.isPublish())){
375 throw new UnpublishedException("Access denied. "+ message);
376 }
377 }
378
379
380
381 }