Project

General

Profile

Download (13.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2009 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.persistence.dao.hibernate.common;
11

    
12
import java.util.ArrayList;
13
import java.util.List;
14
import java.util.Set;
15
import java.util.UUID;
16

    
17
import org.apache.log4j.Logger;
18
import org.hibernate.criterion.Criterion;
19
import org.hibernate.envers.AuditReader;
20
import org.hibernate.envers.AuditReaderFactory;
21
import org.hibernate.envers.query.AuditEntity;
22
import org.hibernate.envers.query.AuditQuery;
23
import org.hibernate.envers.query.criteria.AuditCriterion;
24

    
25
import eu.etaxonomy.cdm.model.common.VersionableEntity;
26
import eu.etaxonomy.cdm.model.view.AuditEvent;
27
import eu.etaxonomy.cdm.model.view.AuditEventRecord;
28
import eu.etaxonomy.cdm.model.view.AuditEventRecordImpl;
29
import eu.etaxonomy.cdm.model.view.context.AuditEventContext;
30
import eu.etaxonomy.cdm.model.view.context.AuditEventContextHolder;
31
import eu.etaxonomy.cdm.persistence.dao.common.AuditEventSort;
32
import eu.etaxonomy.cdm.persistence.dao.common.IVersionableDao;
33
import eu.etaxonomy.cdm.persistence.dao.common.OperationNotSupportedInPriorViewException;
34
import eu.etaxonomy.cdm.persistence.query.MatchMode;
35
import eu.etaxonomy.cdm.persistence.query.OrderHint;
36

    
37
public abstract class VersionableDaoBase<T extends VersionableEntity> extends CdmEntityDaoBase<T> implements IVersionableDao<T> {
38
	private static final Logger logger = Logger.getLogger(VersionableDaoBase.class);
39

    
40
	protected AuditReader getAuditReader() {
41
		return AuditReaderFactory.get(getSession());
42
	}
43

    
44
	public VersionableDaoBase(Class<T> type) {
45
		super(type);
46
	}
47

    
48
	 protected AuditEvent getAuditEventFromContext() {
49
		AuditEventContext auditEventContext = AuditEventContextHolder.getContext();
50

    
51
	   	AuditEvent auditEvent = auditEventContext.getAuditEvent();
52
	   	if(auditEvent != null) {
53
	   		logger.debug(" AuditEvent found, returning " + auditEvent);
54
	  	    return auditEvent;
55
	    } else {
56
	    	logger.debug(" AuditEvent is NULL, returning AuditEvent.CURRENT_VIEW");
57
	   		return AuditEvent.CURRENT_VIEW;
58
	   	}
59
	}
60

    
61
	protected void checkNotInPriorView(String message) {
62
		AuditEvent auditEvent = getAuditEventFromContext();
63
		if(!auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
64
			throw new OperationNotSupportedInPriorViewException(message);
65
		}
66
	}
67

    
68
	@Override
69
	public T findByUuid(UUID uuid) {
70
		AuditEvent auditEvent = getAuditEventFromContext();
71
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
72
			return super.findByUuid(uuid);
73
		} else {
74
			AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
75
			query.add(AuditEntity.property("uuid").eq(uuid));
76
			// TODO initialize bits
77
			return (T)query.getSingleResult();
78
		}
79
	}
80

    
81
    @Override
82
	protected List<T> findByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
83
    	checkNotInPriorView("IdentifiableDaoBase.findByParam(Class<? extends T> clazz, String queryString, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
84
    	return super.findByParam(clazz, param, queryString, matchmode, criterion, pageSize, pageNumber, orderHints, propertyPaths);
85
    }
86

    
87
	@Override
88
	public T load(UUID uuid) {
89
		AuditEvent auditEvent = getAuditEventFromContext();
90
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
91
			return super.load(uuid);
92
		} else {
93
			AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
94
			query.add(AuditEntity.property("uuid").eq(uuid));
95
			T t = (T)query.getSingleResult();
96
			defaultBeanInitializer.load(t);
97
			return t;
98
		}
99
	}
100

    
101
	@Override
102
	public T load(UUID uuid, List<String> propertyPaths) {
103
		AuditEvent auditEvent = getAuditEventFromContext();
104
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
105
			return super.load(uuid,propertyPaths);
106
		} else {
107
			AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
108
			query.add(AuditEntity.property("uuid").eq(uuid));
109
			T t = (T)query.getSingleResult();
110
			defaultBeanInitializer.initialize(t, propertyPaths);
111
			return t;
112
		}
113
	}
114

    
115

    
116
	@Override
117
	public Boolean exists(UUID uuid) {
118
		AuditEvent auditEvent = getAuditEventFromContext();
119
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
120
			return super.exists(uuid);
121
		} else {
122
			AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
123
			query.add(AuditEntity.property("uuid").eq(uuid));
124
			return null != (T)query.getSingleResult();
125
		}
126
	}
127

    
128
	@Override
129
	public int count() {
130
		AuditEvent auditEvent = getAuditEventFromContext();
131
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
132
			return super.count();
133
		} else {
134
			return this.count(null);
135
		}
136
	}
137

    
138
	@Override
139
	public int count(Class<? extends T> clazz) {
140
		AuditEvent auditEvent = getAuditEventFromContext();
141
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
142
			return super.count(clazz);
143
		} else {
144
			AuditQuery query = null;
145
			if(clazz == null) {
146
			    query = getAuditReader().createQuery().forEntitiesAtRevision(type, auditEvent.getRevisionNumber());
147
			} else {
148
				query = getAuditReader().createQuery().forEntitiesAtRevision(clazz, auditEvent.getRevisionNumber());
149
			}
150

    
151
			query.addProjection(AuditEntity.id().count());
152

    
153
			return ((Long)query.getSingleResult()).intValue();
154
		}
155
	}
156

    
157
	@Override
158
	public List<T> list(Integer limit, Integer start) {
159
		AuditEvent auditEvent = getAuditEventFromContext();
160
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
161
			return super.list(limit, start);
162
		} else {
163
			return this.list(null, limit, start);
164
		}
165
	}
166

    
167
	@Override
168
	public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start) {
169
		AuditEvent auditEvent = getAuditEventFromContext();
170
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
171
			return super.list(type,limit, start);
172
		} else {
173
			return this.list(type, limit, start, null,null);
174
		}
175
	}
176

    
177
	@Override
178
	public <S extends T> List<S> list(Class<S> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
179
		AuditEvent auditEvent = getAuditEventFromContext();
180
		if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
181
			return super.list(clazz, limit, start, orderHints, propertyPaths);
182
		} else {
183
			AuditQuery query = null;
184

    
185
			if(clazz == null) {
186
				query = getAuditReader().createQuery().forEntitiesAtRevision(type,auditEvent.getRevisionNumber());
187
			} else {
188
				query = getAuditReader().createQuery().forEntitiesAtRevision(clazz,auditEvent.getRevisionNumber());
189
			}
190

    
191
			addOrder(query,orderHints);
192

    
193
			if(limit != null) {
194
		   	  query.setMaxResults(limit);
195
			  query.setFirstResult(start);
196
			}
197

    
198
			List<S> result = query.getResultList();
199
			defaultBeanInitializer.initializeAll(result, propertyPaths);
200
		    return result;
201
		}
202
	}
203

    
204
	protected void addOrder(AuditQuery query, List<OrderHint> orderHints) {
205
		if(orderHints != null && !orderHints.isEmpty()) {
206
		   for(OrderHint orderHint : orderHints) {
207
			   orderHint.add(query);
208
		   }
209
		}
210
	}
211

    
212
	@Override
213
    public List<AuditEventRecord<T>> getAuditEvents(T t, Integer pageSize, Integer pageNumber, AuditEventSort sort, List<String> propertyPaths) {
214
		AuditEvent auditEvent = getAuditEventFromContext();
215

    
216
		AuditQuery query = getAuditReader().createQuery().forRevisionsOfEntity(type, false, true);
217
		query.add(AuditEntity.id().eq(t.getId()));
218
		if(sort == null) {
219
		  sort = AuditEventSort.BACKWARDS;
220
		}
221

    
222
		if(sort.equals(AuditEventSort.BACKWARDS)) {
223
            if(!auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
224
		  	  query.add(AuditEntity.revisionNumber().lt(auditEvent.getRevisionNumber()));
225
		    }
226
		    query.addOrder(AuditEntity.revisionNumber().desc());
227
     	} else {
228
     		if(!auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
229
  		  	  query.add(AuditEntity.revisionNumber().gt(auditEvent.getRevisionNumber()));
230
  		    }
231
  		    query.addOrder(AuditEntity.revisionNumber().asc());
232
     	}
233

    
234
		if(pageSize != null) {
235
		    query.setMaxResults(pageSize);
236
		    if(pageNumber != null) {
237
		        query.setFirstResult(pageNumber * pageSize);
238
		    } else {
239
		    	query.setFirstResult(0);
240
		    }
241
		}
242

    
243
        /**
244
         * At the moment we need to transform the data manually
245
         */
246
        List<Object[]> objs = query.getResultList();
247
        List<AuditEventRecord<T>> records = new ArrayList<AuditEventRecord<T>>();
248

    
249
        for(Object[] obj : objs) {
250
        	records.add(new AuditEventRecordImpl<T>(obj));
251
        }
252

    
253
        for(AuditEventRecord<T> record : records) {
254
        	defaultBeanInitializer.initialize(record.getAuditableObject(), propertyPaths);
255
        }
256
		return records;
257
	}
258

    
259
	@Override
260
    public int countAuditEvents(T t, AuditEventSort sort) {
261
		AuditEvent auditEvent = getAuditEventFromContext();
262

    
263
		AuditQuery query = getAuditReader().createQuery().forRevisionsOfEntity(type, false, true);
264
		query.add(AuditEntity.id().eq(t.getId()));
265

    
266
		if(!auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
267
			if(sort == null) {
268
				sort = AuditEventSort.BACKWARDS;
269
			}
270

    
271
			if(sort.equals(AuditEventSort.BACKWARDS)) {
272
				query.add(AuditEntity.revisionNumber().lt(auditEvent.getRevisionNumber()));
273
			} else {
274
				query.add(AuditEntity.revisionNumber().gt(auditEvent.getRevisionNumber()));
275
			}
276
		}
277

    
278
		query.addProjection(AuditEntity.revisionNumber().count());
279

    
280
		return ((Long)query.getSingleResult()).intValue();
281
	}
282

    
283
	@Override
284
    public AuditEventRecord<T> getNextAuditEvent(T t) {
285
		List<AuditEventRecord<T>> auditEvents = getAuditEvents(t,1,0,AuditEventSort.FORWARDS, null);
286
		if(auditEvents.isEmpty()) {
287
			return null;
288
		} else {
289
		    return auditEvents.get(0);
290
		}
291
	}
292

    
293
	@Override
294
    public AuditEventRecord<T> getPreviousAuditEvent(T t) {
295
		List<AuditEventRecord<T>> auditEvents = getAuditEvents(t,1,0,AuditEventSort.BACKWARDS, null);
296
		if(auditEvents.isEmpty()) {
297
			return null;
298
		} else {
299
		    return auditEvents.get(0);
300
		}
301
	}
302

    
303
	@Override
304
    public int countAuditEvents(Class<? extends T> clazz, AuditEvent from,	AuditEvent to, List<AuditCriterion> criteria) {
305
		AuditQuery query = null;
306

    
307
		if(clazz == null) {
308
		   query = getAuditReader().createQuery().forRevisionsOfEntity(type, false, true);
309
		} else {
310
		   query = getAuditReader().createQuery().forRevisionsOfEntity(clazz, false, true);
311
		}
312

    
313
		if(from != null) {
314
			query.add(AuditEntity.revisionNumber().ge(from.getRevisionNumber()));
315
		}
316

    
317
		if(to != null && !to.equals(AuditEvent.CURRENT_VIEW)) {
318
			query.add(AuditEntity.revisionNumber().lt(to.getRevisionNumber()));
319
		}
320

    
321
		addCriteria(query,criteria);
322

    
323
		query.addProjection(AuditEntity.revisionNumber().count());
324

    
325
		int result = ((Long)query.getSingleResult()).intValue();
326
		return result;
327
	}
328

    
329
	protected void addCriteria(AuditQuery query, List<AuditCriterion> criteria) {
330
		if(criteria != null) {
331
			for(AuditCriterion c : criteria) {
332
				query.add(c);
333
			}
334
		}
335
	}
336

    
337
	@Override
338
    public List<AuditEventRecord<T>> getAuditEvents(Class<? extends T> clazz,AuditEvent from, AuditEvent to, List<AuditCriterion> criteria,	Integer pageSize, Integer pageNumber, AuditEventSort sort,	List<String> propertyPaths) {
339
        AuditQuery query = null;
340

    
341
		if(clazz == null) {
342
		   query = getAuditReader().createQuery().forRevisionsOfEntity(type, false, true);
343
		} else {
344
		   query = getAuditReader().createQuery().forRevisionsOfEntity(clazz, false, true);
345
		}
346

    
347
		if(from != null) {
348
			query.add(AuditEntity.revisionNumber().ge(from.getRevisionNumber()));
349
		}
350

    
351
		if(to != null && !to.equals(AuditEvent.CURRENT_VIEW)) {
352
			query.add(AuditEntity.revisionNumber().lt(to.getRevisionNumber()));
353
		}
354

    
355
		if(sort.equals(AuditEventSort.BACKWARDS)) {
356
		    query.addOrder(AuditEntity.revisionNumber().desc());
357
     	} else {
358
  		    query.addOrder(AuditEntity.revisionNumber().asc());
359
     	}
360

    
361
		addCriteria(query,criteria);
362

    
363
		if(pageSize != null) {
364
		    query.setMaxResults(pageSize);
365
		    if(pageNumber != null) {
366
		        query.setFirstResult(pageNumber * pageSize);
367
		    } else {
368
		    	query.setFirstResult(0);
369
		    }
370
		}
371

    
372
		/**
373
         * At the moment we need to transform the data manually
374
         */
375
        List<Object[]> objs = query.getResultList();
376
        List<AuditEventRecord<T>> records = new ArrayList<AuditEventRecord<T>>();
377

    
378
        for(Object[] obj : objs) {
379
        	records.add(new AuditEventRecordImpl<T>(obj));
380
        }
381

    
382
        for(AuditEventRecord<T> record : records) {
383
        	defaultBeanInitializer.initialize(record.getAuditableObject(), propertyPaths);
384
        }
385
		return records;
386
	}
387

    
388
	@Override
389
	protected int countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion) {
390
    	checkNotInPriorView("IdentifiableDaoBase.findByParam(Class<? extends T> clazz, String queryString, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
391
    	return super.countByParam(clazz, param, queryString, matchmode, criterion);
392
	}
393

    
394
	@Override
395
	public int count(T example, Set<String> includeProperties) {
396
		this.checkNotInPriorView("count(T example, Set<String> includeProperties)");
397
		return super.count(example, includeProperties);
398
	}
399

    
400
	@Override
401
    public List<T> list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
402
		this.checkNotInPriorView("list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {");
403
		return super.list(example, includeProperties, limit, start, orderHints, propertyPaths);
404
	}
405
}
(23-23/23)