Added comments indicating candidates for harmonisation
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / ServiceBase.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.cdm.api.service;
12
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.UUID;
20
21 import org.apache.log4j.Logger;
22 import org.springframework.beans.factory.annotation.Qualifier;
23 import org.springframework.context.ApplicationContext;
24 import org.springframework.context.ApplicationContextAware;
25 import org.springframework.transaction.TransactionStatus;
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.DefaultPagerImpl;
30 import eu.etaxonomy.cdm.model.common.CdmBase;
31 import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
32 import eu.etaxonomy.cdm.persistence.query.OrderHint;
33
34 @Transactional(readOnly=true)
35 public abstract class ServiceBase<T extends CdmBase, DAO extends ICdmEntityDao<T>> implements IService<T>, ApplicationContextAware {
36 private static final Logger logger = Logger.getLogger(ServiceBase.class);
37
38 //flush after saving this number of objects
39 int flushAfterNo = 2000;
40 protected ApplicationContext appContext;
41
42 @Qualifier("baseDao")
43 protected DAO dao;
44
45 protected abstract void setDao(DAO dao);
46
47 /* (non-Javadoc)
48 * @see eu.etaxonomy.cdm.api.service.Iyyy#setApplicationContext(org.springframework.context.ApplicationContext)
49 */
50 public void setApplicationContext(ApplicationContext appContext){
51 this.appContext = appContext;
52 }
53
54 /**
55 * FIXME Candidate for harmonization
56 * find
57 * @param uuid
58 * @return
59 */
60 public T getCdmObjectByUuid(UUID uuid) {
61 return dao.findByUuid(uuid);
62 }
63
64 /**
65 * FIXME Candidate for harmonization
66 * the generic method arguments are a bit meaningless as
67 * we're not typing the results. this should be changed to
68 * public int count(Class<? extends T> clazz)
69 * where clazz can be null, to count all instances of type T
70 */
71 public <TYPE extends T> int count(Class<TYPE> clazz) {
72 return dao.count(clazz);
73 }
74
75 /**
76 * FIXME Candidate for harmonization
77 * merge with the above
78 */
79 public int count() {
80 return dao.count();
81 }
82
83 /**
84 * FIXME Candidate for harmonization
85 * saveOrUpdate
86 * @param cdmObj
87 * @return
88 */
89 @Transactional(readOnly = false)
90 protected UUID saveCdmObject(T cdmObj){
91 if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}
92 return dao.saveOrUpdate(cdmObj);
93 }
94
95
96 /**
97 * FIXME Candidate for harmonization
98 * @param cdmObj
99 * @return
100 */
101 @Transactional(readOnly = false)
102 protected UUID saveCdmObject(T cdmObj, TransactionStatus txStatus){
103 // TODO: Implement with considering txStatus
104 if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}
105 return dao.saveOrUpdate(cdmObj);
106 }
107
108 /**
109 * FIXME Candidate for harmonization
110 * save(Set<T> ts)
111 * @param <S>
112 * @param cdmObjCollection
113 * @return
114 */
115 @Transactional(readOnly = false)
116 protected <S extends T> Map<UUID, S> saveCdmObjectAll(Collection<? extends S> cdmObjCollection){
117 int types = cdmObjCollection.getClass().getTypeParameters().length;
118 if (types > 0){
119 if (logger.isDebugEnabled()){logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);}
120 }
121
122 Map<UUID, S> resultMap = new HashMap<UUID, S>();
123 Iterator<? extends S> iterator = cdmObjCollection.iterator();
124 int i = 0;
125 while(iterator.hasNext()){
126 if ( ( (i % 5000) == 0) && (i > 0) ){logger.debug("Saved " + i + " objects" );}
127 S cdmObj = iterator.next();
128 UUID uuid = saveCdmObject(cdmObj);
129 // if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}
130 resultMap.put(uuid, cdmObj);
131 i++;
132 if ( (i % flushAfterNo) == 0){
133 try{
134 logger.debug("flush");
135 dao.flush();
136 }catch(Exception e){
137 logger.error("UUUIIIII");
138 e.printStackTrace();
139 }
140 }
141 }
142
143 if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}
144 return resultMap;
145 }
146
147 @Transactional(readOnly = false)
148 public UUID delete(T persistentObject) {
149 return dao.delete(persistentObject);
150 }
151
152 public boolean exists(UUID uuid) {
153 return dao.exists(uuid);
154 }
155
156 /**
157 * FIXME Candidate for harmonization
158 * rename find
159 */
160 public T findByUuid(UUID uuid) {
161 return dao.findByUuid(uuid);
162 }
163
164 public T load(UUID uuid) {
165 return dao.load(uuid);
166 }
167
168 public T load(UUID uuid, List<String> propertyPaths){
169 return dao.load(uuid, propertyPaths);
170 }
171
172 /**
173 * FIXME Candidate for harmonization
174 * should be single method
175 * List<T> list(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths)
176 */
177 public <TYPE extends T> List<TYPE> list(Class<TYPE> type, int limit,int start) {
178 return dao.list(type, limit, start);
179 }
180
181 /**
182 * FIXME Candidate for harmonization
183 * remove
184 */
185 public Pager<T> list(Integer pageSize, Integer pageNumber){
186 return list(pageSize, pageNumber, null);
187 }
188
189 /**
190 * FIXME Candidate for harmonization
191 * should be single method
192 * Pager<T> page(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths)
193 */
194 public Pager<T> list(Integer pageSize, Integer pageNumber, List<OrderHint> orderHints){
195 return list(pageSize,pageNumber,orderHints,null);
196 }
197
198 /**
199 * FIXME Candidate for harmonization
200 * should be single method
201 * Pager<T> page(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths)
202 */
203 public Pager<T> list(Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
204 Integer numberOfResults = dao.count();
205 List<T> results = new ArrayList<T>();
206 pageNumber = pageNumber == null ? 0 : pageNumber;
207 if(numberOfResults > 0) { // no point checking again
208 Integer start = pageSize == null ? 0 : pageSize * (pageNumber - 1);
209 results = dao.list(pageSize, start, orderHints,propertyPaths);
210 }
211 return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
212 }
213
214 /**
215 * FIXME Candidate for harmonization
216 * should be single method
217 * Pager<T> page(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths)
218 */
219 public <TYPE extends T> Pager<TYPE> list(Class<TYPE> type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths){
220 Integer numberOfResults = dao.count(type);
221 List<TYPE> results = new ArrayList<TYPE>();
222 pageNumber = pageNumber == null ? 0 : pageNumber;
223 if(numberOfResults > 0) { // no point checking again
224 Integer start = pageSize == null ? 0 : pageSize * (pageNumber - 1);
225 results = dao.list(type,pageSize, start, orderHints,propertyPaths);
226 }
227 return new DefaultPagerImpl<TYPE>(pageNumber, numberOfResults, pageSize, results);
228 }
229
230 @Transactional(readOnly = false)
231 public UUID save(T newInstance) {
232 return dao.save(newInstance);
233 }
234
235 @Transactional(readOnly = false)
236 public UUID merge(T newInstance) {
237 return dao.merge(newInstance);
238 }
239
240 /**
241 * FIXME Candidate for harmonization
242 * rename -> save
243 */
244 @Transactional(readOnly = false)
245 public Map<UUID, T> saveAll(Collection<T> newInstances) {
246 return dao.saveAll(newInstances);
247 }
248
249 @Transactional(readOnly = false)
250 public UUID saveOrUpdate(T transientObject) {
251 return dao.saveOrUpdate(transientObject);
252 }
253
254 @Transactional(readOnly = false)
255 public UUID update(T transientObject) {
256 return dao.update(transientObject);
257 }
258
259 public UUID refresh(T persistentObject) {
260 return dao.refresh(persistentObject);
261 }
262
263 /**
264 * FIXME Candidate for harmonization
265 * delete
266 * @param cdmObj
267 * @return
268 */
269 @Transactional(readOnly = false)
270 protected UUID removeCdmObject(T cdmObj){
271 if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}
272 return dao.delete(cdmObj);
273 }
274
275 /**
276 * FIXME Candidate for harmonization
277 * should be single method
278 * List<T> list(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths)
279 */
280 public List<T> list(int limit, int start) {
281 return dao.list(limit, start);
282 }
283
284 /**
285 * FIXME Candidate for harmonization
286 * is this method used, and if so, should it be exposed in the service layer?
287 * it seems a bit incongruous that we use an ORM to hide the fact that there is a
288 * database, then expose a method that talks about "rows" . . .
289 */
290 public List<T> rows(String tableName, int limit, int start) {
291 return dao.rows(tableName, limit, start);
292 }
293 }