2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
;
11 import java
.util
.ArrayList
;
12 import java
.util
.List
;
14 import java
.util
.UUID
;
16 import org
.apache
.logging
.log4j
.LogManager
;import org
.apache
.logging
.log4j
.Logger
;
17 import org
.hibernate
.criterion
.Criterion
;
18 import org
.hibernate
.envers
.query
.AuditEntity
;
19 import org
.hibernate
.envers
.query
.AuditQuery
;
20 import org
.hibernate
.envers
.query
.criteria
.AuditCriterion
;
22 import eu
.etaxonomy
.cdm
.model
.common
.VersionableEntity
;
23 import eu
.etaxonomy
.cdm
.model
.view
.AuditEvent
;
24 import eu
.etaxonomy
.cdm
.model
.view
.AuditEventRecord
;
25 import eu
.etaxonomy
.cdm
.model
.view
.AuditEventRecordImpl
;
26 import eu
.etaxonomy
.cdm
.model
.view
.context
.AuditEventContext
;
27 import eu
.etaxonomy
.cdm
.model
.view
.context
.AuditEventContextHolder
;
28 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.AuditEventSort
;
29 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IVersionableDao
;
30 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.OperationNotSupportedInPriorViewException
;
31 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.Restriction
;
32 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
33 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
35 public abstract class VersionableDaoBase
<T
extends VersionableEntity
> extends CdmEntityDaoBase
<T
> implements IVersionableDao
<T
> {
36 private static final Logger logger
= LogManager
.getLogger(VersionableDaoBase
.class);
38 public VersionableDaoBase(Class
<T
> type
) {
42 protected AuditEvent
getAuditEventFromContext() {
43 AuditEventContext auditEventContext
= AuditEventContextHolder
.getContext();
45 AuditEvent auditEvent
= auditEventContext
.getAuditEvent();
46 if(auditEvent
!= null) {
47 logger
.debug(" AuditEvent found, returning " + auditEvent
);
50 logger
.debug(" AuditEvent is NULL, returning AuditEvent.CURRENT_VIEW");
51 return AuditEvent
.CURRENT_VIEW
;
55 protected void checkNotInPriorView(String message
) {
56 AuditEvent auditEvent
= getAuditEventFromContext();
57 if(!auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
58 throw new OperationNotSupportedInPriorViewException(message
);
63 public T
findByUuid(UUID uuid
) {
64 AuditEvent auditEvent
= getAuditEventFromContext();
65 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
66 return super.findByUuid(uuid
);
68 AuditQuery query
= makeAuditQuery(null, auditEvent
);
69 query
.add(AuditEntity
.property("uuid").eq(uuid
));
70 @SuppressWarnings("unchecked")
71 T result
= (T
)query
.getSingleResult();
77 public <S
extends T
> List
<S
> findByParam(Class
<S
> clazz
, String param
, String queryString
, MatchMode matchmode
, List
<Criterion
> criterion
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
78 checkNotInPriorView("IdentifiableDaoBase.findByParam(Class<? extends T> clazz, String queryString, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
79 return super.findByParam(clazz
, param
, queryString
, matchmode
, criterion
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
83 public <S
extends T
> List
<S
> findByParamWithRestrictions(Class
<S
> clazz
, String param
, String queryString
, MatchMode matchmode
, List
<Restriction
<?
>> restrictions
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
84 checkNotInPriorView("IdentifiableDaoBase.findByParam(Class<? extends T> clazz, String queryString, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
85 return super.findByParamWithRestrictions(clazz
, param
, queryString
, matchmode
, restrictions
, pageSize
, pageNumber
, orderHints
, propertyPaths
);
89 public T
load(UUID uuid
) {
90 AuditEvent auditEvent
= getAuditEventFromContext();
91 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
92 return super.load(uuid
);
94 AuditQuery query
= makeAuditQuery(null, auditEvent
);
95 query
.add(AuditEntity
.property("uuid").eq(uuid
));
96 @SuppressWarnings("unchecked")
97 T t
= (T
)query
.getSingleResult();
98 defaultBeanInitializer
.load(t
);
104 public T
load(UUID uuid
, List
<String
> propertyPaths
) {
105 return this.load(uuid
, INCLUDE_UNPUBLISHED
, propertyPaths
);
109 protected T
load(UUID uuid
, boolean includeUnpublished
, List
<String
> propertyPaths
) {
110 AuditEvent auditEvent
= getAuditEventFromContext();
111 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
112 return super.load(uuid
, includeUnpublished
, propertyPaths
);
114 //TODO includeUnpublished
115 AuditQuery query
= makeAuditQuery(null, auditEvent
);
116 query
.add(AuditEntity
.property("uuid").eq(uuid
));
117 @SuppressWarnings("unchecked")
118 T t
= (T
)query
.getSingleResult();
119 defaultBeanInitializer
.initialize(t
, propertyPaths
);
126 public Boolean
exists(UUID uuid
) {
127 AuditEvent auditEvent
= getAuditEventFromContext();
128 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
129 return super.exists(uuid
);
131 AuditQuery query
= makeAuditQuery(null, auditEvent
);
132 query
.add(AuditEntity
.property("uuid").eq(uuid
));
133 return null != query
.getSingleResult();
138 public long count() {
139 AuditEvent auditEvent
= getAuditEventFromContext();
140 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
141 return super.count();
143 return this.count(null);
148 public long count(Class
<?
extends T
> clazz
) {
149 AuditEvent auditEvent
= getAuditEventFromContext();
150 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
151 return super.count(clazz
);
153 AuditQuery query
= makeAuditQuery(clazz
, auditEvent
);
155 query
.addProjection(AuditEntity
.id().count());
157 return (Long
)query
.getSingleResult();
162 public List
<T
> list(Integer limit
, Integer start
) {
163 AuditEvent auditEvent
= getAuditEventFromContext();
164 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
165 return super.list(limit
, start
);
167 return this.list(null, limit
, start
);
172 public <S
extends T
> List
<S
> list(Class
<S
> type
, Integer limit
, Integer start
) {
173 AuditEvent auditEvent
= getAuditEventFromContext();
174 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
175 return super.list(type
,limit
, start
);
177 return this.list(type
, limit
, start
, null,null);
182 public <S
extends T
> List
<S
> list(Class
<S
> clazz
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
183 AuditEvent auditEvent
= getAuditEventFromContext();
184 if(auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
185 return super.list(clazz
, limit
, start
, orderHints
, propertyPaths
);
187 AuditQuery query
= makeAuditQuery(clazz
, auditEvent
);
189 addOrder(query
,orderHints
);
190 addLimitAndStart(query
, limit
, start
);
192 @SuppressWarnings("unchecked")
193 List
<S
> result
= query
.getResultList();
194 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
199 protected void addOrder(AuditQuery query
, List
<OrderHint
> orderHints
) {
200 if(orderHints
!= null && !orderHints
.isEmpty()) {
201 for(OrderHint orderHint
: orderHints
) {
202 orderHint
.add(query
);
208 public List
<AuditEventRecord
<T
>> getAuditEvents(T t
, Integer pageSize
, Integer pageNumber
, AuditEventSort sort
, List
<String
> propertyPaths
) {
209 AuditEvent auditEvent
= getAuditEventFromContext();
211 AuditQuery query
= getAuditReader().createQuery().forRevisionsOfEntity(type
, false, true);
212 query
.add(AuditEntity
.id().eq(t
.getId()));
214 sort
= AuditEventSort
.BACKWARDS
;
217 if(sort
.equals(AuditEventSort
.BACKWARDS
)) {
218 if(!auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
219 query
.add(AuditEntity
.revisionNumber().lt(auditEvent
.getRevisionNumber()));
221 query
.addOrder(AuditEntity
.revisionNumber().desc());
223 if(!auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
224 query
.add(AuditEntity
.revisionNumber().gt(auditEvent
.getRevisionNumber()));
226 query
.addOrder(AuditEntity
.revisionNumber().asc());
229 if(pageSize
!= null) {
230 query
.setMaxResults(pageSize
);
231 if(pageNumber
!= null) {
232 query
.setFirstResult(pageNumber
* pageSize
);
234 query
.setFirstResult(0);
239 * At the moment we need to transform the data manually
241 @SuppressWarnings("unchecked")
242 List
<Object
[]> objs
= query
.getResultList();
243 List
<AuditEventRecord
<T
>> records
= new ArrayList
<AuditEventRecord
<T
>>();
245 for(Object
[] obj
: objs
) {
246 records
.add(new AuditEventRecordImpl
<T
>(obj
));
249 for(AuditEventRecord
<T
> record
: records
) {
250 defaultBeanInitializer
.initialize(record
.getAuditableObject(), propertyPaths
);
256 public long countAuditEvents(T t
, AuditEventSort sort
) {
257 AuditEvent auditEvent
= getAuditEventFromContext();
259 AuditQuery query
= getAuditReader().createQuery().forRevisionsOfEntity(type
, false, true);
260 query
.add(AuditEntity
.id().eq(t
.getId()));
262 if(!auditEvent
.equals(AuditEvent
.CURRENT_VIEW
)) {
264 sort
= AuditEventSort
.BACKWARDS
;
267 if(sort
.equals(AuditEventSort
.BACKWARDS
)) {
268 query
.add(AuditEntity
.revisionNumber().lt(auditEvent
.getRevisionNumber()));
270 query
.add(AuditEntity
.revisionNumber().gt(auditEvent
.getRevisionNumber()));
274 query
.addProjection(AuditEntity
.revisionNumber().count());
276 return (Long
)query
.getSingleResult();
280 public AuditEventRecord
<T
> getNextAuditEvent(T t
) {
281 List
<AuditEventRecord
<T
>> auditEvents
= getAuditEvents(t
,1,0,AuditEventSort
.FORWARDS
, null);
282 if(auditEvents
.isEmpty()) {
285 return auditEvents
.get(0);
290 public AuditEventRecord
<T
> getPreviousAuditEvent(T t
) {
291 List
<AuditEventRecord
<T
>> auditEvents
= getAuditEvents(t
,1,0,AuditEventSort
.BACKWARDS
, null);
292 if(auditEvents
.isEmpty()) {
295 return auditEvents
.get(0);
300 public long countAuditEvents(Class
<?
extends T
> clazz
, AuditEvent from
, AuditEvent to
, List
<AuditCriterion
> criteria
) {
301 AuditQuery query
= null;
304 query
= getAuditReader().createQuery().forRevisionsOfEntity(type
, false, true);
306 query
= getAuditReader().createQuery().forRevisionsOfEntity(clazz
, false, true);
310 query
.add(AuditEntity
.revisionNumber().ge(from
.getRevisionNumber()));
313 if(to
!= null && !to
.equals(AuditEvent
.CURRENT_VIEW
)) {
314 query
.add(AuditEntity
.revisionNumber().lt(to
.getRevisionNumber()));
317 addCriteria(query
,criteria
);
319 query
.addProjection(AuditEntity
.revisionNumber().count());
321 return (Long
)query
.getSingleResult();
324 protected void addCriteria(AuditQuery query
, List
<AuditCriterion
> criteria
) {
325 if(criteria
!= null) {
326 for(AuditCriterion c
: criteria
) {
333 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
) {
334 AuditQuery query
= null;
337 query
= getAuditReader().createQuery().forRevisionsOfEntity(type
, false, true);
339 query
= getAuditReader().createQuery().forRevisionsOfEntity(clazz
, false, true);
343 query
.add(AuditEntity
.revisionNumber().ge(from
.getRevisionNumber()));
346 if(to
!= null && !to
.equals(AuditEvent
.CURRENT_VIEW
)) {
347 query
.add(AuditEntity
.revisionNumber().lt(to
.getRevisionNumber()));
350 if(sort
.equals(AuditEventSort
.BACKWARDS
)) {
351 query
.addOrder(AuditEntity
.revisionNumber().desc());
353 query
.addOrder(AuditEntity
.revisionNumber().asc());
356 addCriteria(query
,criteria
);
358 if(pageSize
!= null) {
359 query
.setMaxResults(pageSize
);
360 if(pageNumber
!= null) {
361 query
.setFirstResult(pageNumber
* pageSize
);
363 query
.setFirstResult(0);
368 * At the moment we need to transform the data manually
370 @SuppressWarnings("unchecked")
371 List
<Object
[]> objs
= query
.getResultList();
372 List
<AuditEventRecord
<T
>> records
= new ArrayList
<>();
374 for(Object
[] obj
: objs
) {
375 records
.add(new AuditEventRecordImpl
<>(obj
));
378 for(AuditEventRecord
<T
> record
: records
) {
379 defaultBeanInitializer
.initialize(record
.getAuditableObject(), propertyPaths
);
385 public long countByParam(Class
<?
extends T
> clazz
, String param
, String queryString
, MatchMode matchmode
, List
<Criterion
> criterion
) {
386 checkNotInPriorView("IdentifiableDaoBase.findByParam(Class<? extends T> clazz, String queryString, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
387 return super.countByParam(clazz
, param
, queryString
, matchmode
, criterion
);
391 public long count(T example
, Set
<String
> includeProperties
) {
392 this.checkNotInPriorView("count(T example, Set<String> includeProperties)");
393 return super.count(example
, includeProperties
);
397 public <S
extends T
> List
<S
> list(S example
, Set
<String
> includeProperties
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
398 this.checkNotInPriorView("list(S example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {");
399 return super.list(example
, includeProperties
, limit
, start
, orderHints
, propertyPaths
);